我正在使用MinGW工具链构buildWindowsdynamic库。
要build立这个库,我静态地链接到其他2提供了一个API,我有一个.def
文件,我写了唯一的符号,我想在我的图书馆出口。
问题是GCC正在导出所有的符号,包括我链接的库中的符号。 是否有告诉链接器只是导出def
文件中的符号?
我知道有选项--export-all-symbols
但似乎没有相反的意思。
现在构build脚本的最后一行有这样的结构:
g++ -shared CXXFLAGS DEFINES INCLUDES -o library.dll library.cpp DEF_FILE \ OBJECT_FILES LIBS -Wl,--enable-stdcall-fixup
编辑:在关于链接器的文档中 ,它表示--export-all-symbols
是默认行为,当你不提供def
文件时,如果你不提供def
文件,它将被禁用。 无论如何,第三方库中的符号都被导出。
编辑:添加选项--exclude-libs LIBS
或–exclude-symbols SYMBOLS
不会阻止导出库中的符号。
如果您的binutils(本地编译或交叉编译)提供了它,您可以使用dllwrap。
它可以使用DEF文件中的接口来生成DLL(在这种情况下,它调用gcc,ld和dlltool来执行此操作)。 使用这个和将DEF文件直接传递给GCC的区别在于文件中的定义被区别对待。
例如,如果在导出文件中有一个符号重命名:
_SomeFuntion = _SomeFunction@12
海湾合作委员会将创建2出口,一个由_SomeFunction
名称和另一个与装饰名称,而dllwrap将只会导出_SomeFuntion
。 所以,如果你只添加到DEF文件中,你想要导出的符号将只在库中与它们结束。
dllwrap默认使用C编译器驱动程序,因为它无法知道其他情况。 在链接C ++代码时,必须使用选项--driver-name c++
来设置驱动程序。 如果你碰巧拥有带有前缀的MinGW可执行文件,你也必须在驱动程序名称中包含它(例如i686-mingw32-c++
而不是c++
),而且你也可能需要使用选项--dlltool-name
。
尝试使用这两行代替您发布的代码:
g++ -c CXXFLAGS DEFINES INCLUDES -o library.o library.cpp dllwrap -o library.dll --driver-name c++ --def DEF_FILE OBJECT_FILES LIBS -Wl,--enable-stdcall-fixup
第一个从library.cpp
的代码生成一个目标文件,第二个组装动态库。 OBJECT_FILES
东西(我认为是以前生成的其他对象文件)应该有library.o
。
也就是说,我必须告诉你,dllwrap在2006年已经被弃用了,官方的binutils包里没有任何文档。 得到一些信息,你可以像平常一样用--help
来调用它。 它可以生成一个导入库,以防您也需要它。
不知道为什么没有真正的答案,但这是对我有用:
汇编你的目标文件
g++ -O0 -gdwarf-4 dll\dllmain.cpp -c -o dllmain.o
链接( -Wl,--exclude-all-symbols
很重要):
g++ -Wl,--enable-auto-import -Wl,--out-implib,libsomelib.a -Wl,--exclude-all-symbols -shared dllmain.o -o somelib.dll
然后,您可以选择在DLL的源代码中直接导出哪些函数:
#include <windows.h> __declspec(dllexport) void someExportedFunction() { MessageBox(NULL, "msgbox", "msgbox", MB_OK); } void nonExportedFunction() { MessageBox(NULL, "notexported", "notexported", MB_OK); }
验证:
C:\libtest>pedump -E somelib.dll === EXPORTS === # module "somelib.dll" # flags=0x0 ts="2014-02-20 08:37:48" version=0.0 ord_base=1 # nFuncs=1 nNames=1 ORD ENTRY_VA NAME 1 1570 _Z20someExportedFunctionv
( pedump
= http://pedump.me )
这是一个经常性的问题。 SO中有两个相关的问题:
和外面SO:
即Windows平台上的全局/本地导出不是在链接器级别处理,而是提供.def
文件以补充.dll
。
缺乏一个好的答案,我做了一个python脚本,照顾从DLL导出表中删除的东西,你可以在这里找到它。
您是否在您提供链接的页面上阅读了此内容,如果–export-all-symbols没有明确使用,则关于行为 – 在以下情况下自动导出被禁用:
任何对象文件中的任何符号都标有__declspec(dllexport)属性。
你有没有尝试明确地只导出你感兴趣的功能? 在DEF文件中弄错名称是很容易的,因为这个方法比较可靠。
您可以使用选项-Wl,--retain-symbols-file=file
,然后在-Wl,--retain-symbols-file=file
列出要保留的符号(每行一个)。 这将导致链接器放弃所有其他符号,只保留你想要的。
免责声明:我只在Linux上这样做,但AFAIK它也应该在Windows上工作
您可以使用-fvisibility=hidden
选项; 有关更多信息,请参阅http://gcc.gnu.org/wiki/Visibility