【问题标题】:.dll Plugin that uses functions defined in the main executable.dll 使用在主可执行文件中定义的函数的插件
【发布时间】:2013-03-05 11:59:05
【问题描述】:

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

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

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

什么是在 Windows 中“使其工作”的最佳方式,但在没有一百万 #ifdef 的情况下保持它与 Linux 兼容?

【问题讨论】:

  • 能否至少分享一下插件的接口头?
  • interface: privatepaste.com/c6118a7e85 example_plugin: privatepaste.com/dd152f6c64 session->Send() == void session::Send(CString str) {...通过套接字发送一些东西...}
  • 我已经直接在问题中发布了标题,看来标题已准备好从 Windows POV 滚动...
  • 是的,标头有效,session->Send() 是问题,vs 链接器叫“未定义的引用”
  • 嘿,我知道这很旧:您最终使用了什么解决方案?为可执行文件制作导入库对您有用吗?还是您最终使用了@DavidHeffernan 提出的其他解决方案之一

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


【解决方案1】:

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

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

其他一些选项:

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      在使用mingw时,可以通过为可执行文件生成一个导入库来完成,如下所示:

      $ dlltool --export-all-symbols <program>.exe -l lib<program>.a -D <program>.exe
      

      -l 参数指定要创建的库的文件名,-D 参数指定库的 dll 名称(重要的是它与程序名称相同)。要编译 dll,您需要通过将 -l&lt;program&gt; 添加到链接器标志来链接导入库。

      如果要限制导出符号,可以先生成一个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 窗口)。

      【讨论】:

      • 您好,这种方法对您有用吗?使用 LoadLibrary 加载插件时出现错误代码 127。
      【解决方案4】:

      我遇到了同样的问题 - 对于专有应用程序 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-29
        • 2020-07-16
        • 2016-12-12
        相关资源
        最近更新 更多