6

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

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

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

在 Windows 中“让它工作”但保持它与 Linux 兼容而没有一百万个的最佳方法是#ifdef什么?

4

4 回答 4

5

Windows 上的库链接处理方式与 Linux 上的处理方式完全不同。从插件链接到主机可执行文件在 Linux 上很简单,但在 Windows 上则不然。

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

其他一些选项:

  1. 从可执行文件中导出函数,并GetProcAddress在您的插件中使用以在运行时绑定到它们。
  2. 初始化插件时,传递一个包含它们需要的所有功能的接口。
于 2013-03-16T21:42:46.240 回答
3

使用 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 环境而异(即i686-w64-mingw32-dlltool在Fedora 上用于交叉编译到i686 windows)。

于 2013-08-09T13:27:52.510 回答
2

要从 DLL 调用可执行文件中定义的函数,您必须使用 __declspec(dllexport) 从可执行文件导出这些函数,就像从 DLL 导出函数一样。

编译器将为可执行文件生成一个导入库,其中包括导出函数的存根。

构建 DLL 时与此导入库链接。

于 2013-03-18T02:12:56.607 回答
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

[另请参阅使用从导入库 (.lib) 转换的库文件 (.a) 使用 gcc 构建 dll

最终,在 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
于 2014-11-13T09:51:32.397 回答