我有一个不依赖CRT或windows sdk的小项目。为了链接到 kernel32.dll,我创建了一个最小的 .def 文件,其中仅包含我需要的几个函数:
LIBRARY kernel32.dll
EXPORTS
ExitProcess
然后我在构建过程中使用以下命令创建 .lib:
lib /DEF:kernel32.def /OUT:kernel32.lib /MACHINE:x86
。
我的代码中函数的声明如下所示:
#ifdef __cplusplus
extern "C"{
#endif
__declspec(dllimport) __declspec(noreturn) void __stdcall ExitProcess(UINT uExitCode);
#ifdef __cplusplus
}
#endif
在编译和链接 x64 时效果非常好(使用 /MACHINE:x64 创建的库),但是当我切换到 x86 时,我收到
__imp__ExitProcess@4
的未解析符号错误。
通过将 def 文件中的导出名称更改为
ExitProcesss@4
可以解决此链接器错误,但在运行程序时,会出现错误,提示 The procedure entry point 'ExitProcess@4' was not found in MyProgram.exe
。
如果我从 Windows sdk 链接到 kernel32.lib,一切都会正常。所以问题一定是在创建 def 文件和创建导入库之间。
我能找到的唯一参考是 mingw 的 .def 文件,它看起来与我的完全一样:https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-crt/lib32/kernel32.def 尽管由于该文件可能由 mingw 工具使用,但它的输出可能与 msvc 中的 lib 工具不同。
只有 def 文件不够,以防此处出现 x86。
if 在 def 中将是名称
ExitProcess
- 在 lib 中也将是 __imp_ExitProcess
。但客户等待__imp__ExitProcess@4
。所以你在构建时失败了。
如果你设置了
ExitProcess@4
你的PE将从kernel32.dll导入
_ExitProcess@4
并在运行时失败
此处的解决方案将 c/cpp/asm 文件与 def
结合使用最小解决方案:首先使用这样的kernel32.asm
.686
.model flat
.code
_ExitProcess@4 proc
_ExitProcess@4 endp
end
并将其编译为
ml /c /Cp kernel32.asm
def 就是这样
EXPORTS
ExitProcess
最后使用下一个命令
link /DLL /NOENTRY /MACHINE:x86 /def:kernel32.def kernel32.obj
在此之后,您得到了正确的kernel32.lib(kernel32.dll和kernel32.exp易于删除)