我有一个可加载的主要可执行文件。dll
/ .so
插件,在Linux上运行得很好但在Windows上运行(Visual Studio 2012),它因未定义的引用错误而失败。
该插件使用在{main}可执行文件中定义的session->SendLine("bla")
等函数。 (在插件中包含的.h中定义的会话和方法类,但在主exec中编译的.cpp中的实际函数)。
tl; dr:"我需要Windows链接器忽略插件中未定义的引用,在主可执行文件中定义"
让它发挥作用的最佳方法是什么?在Windows中,但在没有百万#ifdef
的情况下保持与Linux兼容?
答案 0 :(得分:3)
在Windows上链接库的处理方式与在Linux上处理它的方式完全不同。从插件到主机可执行文件的链接在Linux上很简单,但在Windows上却没有那么多。
在Windows上,链接到外部模块的传统方法是使用由.lib文件提供的导入库。为了这样做,您需要为可执行文件创建一个导入库,其中包含插件需要调用的所有导出函数。我从来没有为可执行文件创建导入库。通常你是为DLL做的。我甚至不确定它是否适用于可执行文件。
其他一些选择:
GetProcAddress
在运行时绑定到它们。答案 1 :(得分:2)
要从DLL调用可执行文件中定义的函数,必须使用__declspec(dllexport)从可执行文件中导出这些函数,就像从DLL导出函数一样。
编译器将为可执行文件生成一个导入库,其中包含导出函数的存根。
在构建DLL时链接此导入库。
答案 2 :(得分:2)
使用mingw时,可以通过为可执行文件生成导入库来完成此操作,如下所示:
$ dlltool --export-all-symbols <program>.exe -l lib<program>.a -D <program>.exe
-l
参数指定要创建的库的文件名,-D
参数指定库的dllname(重要的是它等于程序名称)。要编译dll,您需要通过将-l<program>
添加到链接器标志来链接导入库。
如果要限制导出的符号,可以先生成defs文件,编辑它,然后从defs文件生成导入库:
$ dlltool --export-all-symbols <program>.exe -z <program>.defs
$ vi <program>.defs # Edit the list of exported symbols
$ dlltool -d <program>.defs -l lib<program>.a -D <program>.exe
注意: dlltool的名称可能因mingw环境而异(即Fedora上的i686-w64-mingw32-dlltool
用于交叉编译到i686窗口。)
答案 3 :(得分:0)
我有同样的问题 - 对于专有应用程序 a.exe ,我想构建一个插件, p.dll 。
一篇帖子建议:
$ dlltool --export-all-symbols a.exe -z a.defs
dlltool: a.exe: no symbols
但是 a.exe 附带了一个 a.lib 文件。再一次,没有[有用的]出口:
$ dlltool --export-all-symbols a.lib -z a.defs
$ cat a.defs
; dlltool --export-all-symbols -z a.defs q.lib
EXPORTS
_NULL_IMPORT_DESCRIPTOR @ 1 DATA
_IMPORT_DESCRIPTOR_a @ 2 DATA
[另见Building a dll with a gcc using a library file (.a) converted from import library (.lib)
最终,在MinGW邮件列表上找到提示 nm 是我的解决方案:
$ echo EXPORTS >a.def
$ nm -p a.lib |egrep 'T _' |sed 's/0* T _//' >>a.def
一旦有了这个.def文件,就很容易了:
$ #generate liba.a that has the callbacks for the symbols in *a.exe* (what a.lib has, too)
$ dlltool -v -l liba.a -d a.def
$ #build my plugin, linking to liba.a
$ gcc -shared p.c -L. -la -o p.dll