.dll插件,它使用主可执行文件中定义的函数

时间:2013-03-16 21:36:01

标签: c++ plugins dll visual-studio-2012 undefined-reference

我有一个可加载的主要可执行文件。dll / .so插件,在Linux上运行得很好但在Windows上运行(Visual Studio 2012),它因未定义的引用错误而失败。

该插件使用在{main}可执行文件中定义的session->SendLine("bla")等函数。 (在插件中包含的.h中定义的会话和方法类,但在主exec中编译的.cpp中的实际函数)。

tl; dr:"我需要Windows链接器忽略插件中未定义的引用,在主可执行文件中定义"

让它发挥作用的最佳方法是什么?在Windows中,但在没有百万#ifdef的情况下保持与Linux兼容?

4 个答案:

答案 0 :(得分:3)

在Windows上链接库的处理方式与在Linux上处理它的方式完全不同。从插件到主机可执行文件的链接在Linux上很简单,但在Windows上却没有那么多。

在Windows上,链接到外部模块的传统方法是使用由.lib文件提供的导入库。为了这样做,您需要为可执行文件创建一个导入库,其中包含插件需要调用的所有导出函数。我从来没有为可执行文件创建导入库。通常你是为DLL做的。我甚至不确定它是否适用于可执行文件。

其他一些选择:

  1. 从可执行文件导出函数,并使用插件中的GetProcAddress在运行时绑定到它们。
  2. 初始化插件时,请传递包含所需功能的界面。

答案 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