如何静态链接仅按序号导出的DLL函数?(Visual Studio环境)
如何在Visual Studio C++中通过序号静态链接DLL导出函数
刚好之前折腾过VS下按序号静态链接仅导出序号的DLL函数的需求,给你分享两种实用的方法,一步步就能搞定:
方法一:自定义.def文件生成导入库
因为目标DLL只通过序号1导出TestFunc01,我们需要手动创建一个.def文件来帮链接器建立“函数名-序号”的映射,具体步骤:
- 新建一个.def文件(比如命名为
MyImport.def),写入以下内容:
LIBRARY DllName EXPORTS TestFunc01 @1
这里不要加原DLL.def里的NONAME,我们需要给这个序号绑定一个名字,方便自己的代码调用。
2. 生成导入库:打开Visual Studio的开发者命令提示符,执行lib.exe命令(根据你的项目位数选择参数):
# 32位项目 lib /def:MyImport.def /out:MyImport.lib /machine:x86 # 64位项目 lib /def:MyImport.def /out:MyImport.lib /machine:x64
- 在你的C++项目中,把生成的
MyImport.lib添加到项目属性→链接器→输入→附加依赖项里,然后代码里就可以正常使用原函数声明调用了:
extern "C" __declspec(dllimport) int TestFunc01(int v); int _tmain(int argc, _TCHAR* argv[]) { TestFunc01(123); }
方法二:直接在代码中使用链接器指令(无需额外生成导入库)
这种方法更轻量化,不用手动生成导入库,直接通过#pragma comment给链接器传递指令,绑定函数到指定序号:
你可以直接用原函数名,代码更直观:
// 声明导入函数 extern "C" __declspec(dllimport) int TestFunc01(int v); // 告诉链接器:这个TestFunc01对应DllName.dll中的序号1 #pragma comment(linker, "/export:TestFunc01=DllName.#1") int _tmain(int argc, _TCHAR* argv[]) { TestFunc01(123); }
或者也可以自定义函数名(比如TestFuncByOrdinal),只要链接器指令里对应好就行:
extern "C" __declspec(dllimport) int TestFuncByOrdinal(int v); #pragma comment(linker, "/export:TestFuncByOrdinal=DllName.#1") int _tmain(int argc, _TCHAR* argv[]) { TestFuncByOrdinal(123); }
这里的#1就是指定目标函数的导出序号,DllName是你要链接的DLL文件名(不用加.dll后缀)。
注意事项
- 不管用哪种方法,都要确保
DllName.dll在程序运行时能被找到(比如放到项目输出目录或者系统PATH路径下) - 如果你用的是64位项目,执行
lib.exe时一定要指定/machine:x64,32位项目对应x86,否则生成的导入库会和项目位数不匹配 - 链接器指令里的DLL名字不区分大小写,但尽量和实际DLL文件名保持一致,避免不必要的问题
内容的提问来源于stack exchange,提问作者c00000fd




