在没有 .lib 文件的程序集中调用 DLL 的导出函数
Posted
技术标签:
【中文标题】在没有 .lib 文件的程序集中调用 DLL 的导出函数【英文标题】:Call exported functions of DLL in assembly without .lib file 【发布时间】:2021-02-15 13:07:20 【问题描述】:所以我目前正在尝试在我的程序集文件中调用 dll 的导出函数。
DLL 与我的 asm 程序在同一目录中,我没有 .lib
文件。
这是我的代码:
EXTERN __imp__CreateCompressor@12:PROC
EXTERN __imp__Compress@24:PROC
EXTERN __imp__CloseCompressor@4:PROC
.code
START:
push 2 ;COMPRESS_ALGORITHM_MSZIP
push 0
push OFFSET hCompress
call __imp__CreateCompressor@12
push 0 ;CompressedDataSize
push DWORD ptr [DataSize] ;CompressedBufferSize
push eax ;CompressedBuffer
push DWORD ptr [DataSize]
push DWORD ptr [pBuf3]
push DWORD ptr [hCompress]
call __imp__Compress@24
push DWORD ptr [hCompress]
call __imp__CloseCompressor@4
END START
但是我得到了错误:
file.obj : error LNK2001: unresolved external symbol ___imp__CreateCompressor@12
file.obj : error LNK2001: unresolved external symbol ___imp__Compress@24
file.obj : error LNK2001: unresolved external symbol ___imp__CloseCompressor@4
file.exe : fatal error LNK1120: 3 unresolved externals
我是这样组装的:
ml file.asm /link /subsystem:console /entry:START
有什么想法吗?
【问题讨论】:
EXTERN __imp__CreateCompressor@12:DWORD
必须是。不是PROC
等等 __imp_ 符号
比你需要添加 Cabinet.lib 用于链接器输入
您必须拥有 .lib 文件才能解决链接器错误。不难获得,它包含在 Windows SDK 中。
【参考方案1】:
您必须使用LoadLibrary()
和GetProcAddress()
函数来加载库并从您要调用的函数中获取地址。
【讨论】:
可以,但不是必须的。与 Cabinet.lib 更好的链接 @RbMm,OP说他没有lib
文件,所以他必须动态加载dll
。
这个库是 microsoft SDK 的一部分。所以所有需要 - 只需下载它
@RbMm,在这种情况下,这确实是一个解决方案。 :)
lib-files 并不是特别神奇,您可以获取函数名称列表并使用 lib
实用程序从中制作 lib-file .. OP 甚至没有需要这样做,因为这个 lib-file 已经存在【参考方案2】:
要启用Load-Time Dynamic Linking,链接器需要一个导入库。
如果没有导入库,您将不得不使用Run-Time Dynamic Linking。
或者,您可以自己生成一个导入库。最简单的方法是编写一个适当的Module-Definition (.Def) File 并让Microsoft Librarian Manager (LIB.exe) 生成一个导入库。
【讨论】:
不认为 .def 在这里就足够了。如果只使用def,我们无法设置多少个参数有作用。所以不可能生成说__imp__Compress@24
。但可能将 def 与 c/c++ 结合使用,我们在其中定义了虚拟函数“实现”,例如void __stdcall Compress(int,int,int,int,int,int)
- 这已经在 lib 中给出了__imp__Compress@24
@rbm .def 文件足以创建导入库。导入库足以描述在哪里可以找到符号,这就是问题所要求的。
你错了 - 链接器怎么知道,如何只在 x86 中用 def 装饰符号?如果我们声明Compress
- lib 中必须有什么符号? _Compress
? _Compress@0
? _Compress@4
? _Compress@24
? _Compress@32
? @Compress@8
?
@rbm 没有人建议链接器需要猜测。链接器只解析符号。由于 .def 文件包含修饰符号名称,因此在使用从该 .def 文件生成的导入库时无需进行事后猜测。
好的,我们把Compress@24
放到def文件中。链接器将_Compress@24
和__imp__Compress@24
放入库中,但_Compress@24
在生成的PE 中作为导入名称。但我们需要Compress
(因为cabinet.dll导出这样的Compress
没有装饰)以上是关于在没有 .lib 文件的程序集中调用 DLL 的导出函数的主要内容,如果未能解决你的问题,请参考以下文章
Android studio - 从 dll 文件或 lib 文件调用函数
如何在使用反射加载的程序集中使用 Castle.Windsor