我在MSVC2017中具有以下情形:
bool foo()
foo()
调用GetProcAddress
的应用程序在静态库中,foo()
的定义如下:
extern "C" __declspec(dllexport) bool foo()
{
return true;
}
现在,由于动态链接库未使用foo()
,因此不会导出其符号,因此在应用程序使用GetProcAddress
时找不到该符号。
我尝试过:
#pragma comment(linker, "/include:foo")
和:
#pragma comment(linker, "/export:foo")
如果我将定义移至动态链接库(不是可行的解决方案),则可以使用Dependency Walker看到导出的foo()
,但是当我将定义保留在静态库中时,似乎无法导出符号使用上述链接器开关。我认为这是因为该符号仍未使用,因此无论如何仍不会导出?
我想要Windows上的MSVC和Linux上的Clang的解决方案。谢谢!
答案 0 :(得分:0)
最后,我的解决方案是制作一个名为foo()
的虚拟函数,以强制导出该编译单元中的所有符号。
答案 1 :(得分:0)
您做错了(或至少没有按照问题中的描述进行操作)。当然,您在答案中发布的内容也可以使用,但这只是一种解决方法,因为“常规”方式应该可以使用。
这是一个小例子。
lib.cpp :
extern "C" __declspec(dllexport) bool foo() {
return true;
}
dll.cpp :
extern "C" __declspec(dllexport) bool bar() {
return false;
}
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q056330888]> sopr.bat *** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages *** [prompt]> "c:\Install\x86\Microsoft\Visual Studio Community\2017\VC\Auxiliary\Build\vcvarsall.bat" x64 ********************************************************************** ** Visual Studio 2017 Developer Command Prompt v15.9.13 ** Copyright (c) 2017 Microsoft Corporation ********************************************************************** [vcvarsall.bat] Environment initialized for: 'x64' [prompt]> dir /b dll.cpp lib.cpp [prompt]> cl /c /nologo /D_LIB /DSTATIC /Folib.obj lib.cpp lib.cpp [prompt]> lib /nologo /out:lib.lib lib.obj [prompt]> [prompt]> cl /c /nologo /DDLL /Fodll.obj dll.cpp dll.cpp [prompt]> link /nologo /dll /out:dll.dll dll.obj lib.lib Creating library dll.lib and object dll.exp [prompt]> dir /b dll.cpp dll.dll dll.exp dll.lib dll.obj lib.cpp lib.lib lib.obj [prompt]> dumpbin /nologo /exports dll.dll Dump of file dll.dll File Type: DLL Section contains the following exports for dll.dll 00000000 characteristics FFFFFFFF time date stamp 0.00 version 1 ordinal base 1 number of functions 1 number of names ordinal hint RVA name 1 0 00001000 bar Summary 2000 .data 1000 .pdata 9000 .rdata 1000 .reloc B000 .text [prompt]> [prompt]> rem Re-link dll, instructing it to include foo [prompt]> link /nologo /dll /include:foo /out:dll.dll dll.obj lib.lib Creating library dll.lib and object dll.exp [prompt]> dumpbin /nologo /exports dll.dll Dump of file dll.dll File Type: DLL Section contains the following exports for dll.dll 00000000 characteristics FFFFFFFF time date stamp 0.00 version 1 ordinal base 2 number of functions 2 number of names ordinal hint RVA name 1 0 00001000 bar 2 1 00001010 foo Summary 2000 .data 1000 .pdata 9000 .rdata 1000 .reloc B000 .text
注释:
/include:foo
(2 nd link 命令)也将导出 foo (如下一个 dumpbin中所示) 输出):
#pragma comment(linker, "/include:foo")
(在 dll.cpp 中-或直接传递到链接器的任何文件)相同/export:foo
是不必要的,因为该功能已由__declspec(dllexport)
导出@ EDIT0 :
您可能根本没有做错任何事情。看[MS.Docs]: Overview of LIB,它在导出内容方面提供了与 link 相同的选项。但是它们似乎被忽略了。
构建lib时,也许构建 .lib #pragma comment)。 > ,而不是链接时。显然,它们会被忽略(我已经测试过),除非在直接传递给链接器的 .obj 文件(或选项)中指定了内容。我不知道为什么,也许与[MS.Docs]: Building an Import Library and Export File有关:
请注意,如果在准备步骤中创建导入库,则在创建.dll之前,必须在构建.dll时传递与构建导入库时传递的对象集相同的对象文件。
无论如何,我尝试通过从 .lib 中提取 lib.obj 来完成上述操作(它的大小与我用来创建的大小不同> .lib ,然后将其传递给链接器,但该函数仍未导出。注意,如果我直接将(原始) lib.obj (带有#pragma comment (linker, /include:foo
)传递给链接器,它将导出 foo 。