简体   繁体   English

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

[英].dll Plugin that uses functions defined in the main executable

I have a Main executable that loads . 我有一个主要的可执行文件加载。 dll / .so Plugins, which works just fine in Linux but on windows(Visual Studio 2012), it fails with undefined reference errors. dll / .so插件,在Linux上运行得很好但在Windows上运行(Visual Studio 2012),它因未定义的引用错误而失败。

The plugin uses functions like session->SendLine("bla") which are defined in the Main executable. 该插件使用session->SendLine("bla")等函数,这些函数在Main可执行文件中定义。 (class of session ans methods defined in a .h included in the plugin, but the actual function in a .cpp compiled in main exec). (在插件中包含的.h中定义的会话和方法类,但是在main exec中编译的.cpp中的实际函数)。

tl;dr: "I need the windows linker to ignore undefined references in plugins, defined in the main executable" tl; dr:“我需要Windows链接器来忽略插件中未定义的引用,在主可执行文件中定义”

What is the best way to "make it work" in windows but keep it compatible with Linux without a million #ifdef 's? 在Windows中“使其工作”的最佳方法是什么,但在没有百万#ifdef的情况下保持与Linux兼容?

Linking of libraries on Windows is handled completely differently from how it is handled on Linux. Windows上的库链接处理方式与在Linux上处理它的方式完全不同。 Linking from plugin to host executable is simple on Linux, but not so much on Windows. 从插件到主机可执行文件的链接在Linux上很简单,但在Windows上却没有那么多。

On Windows the traditional way to link to an external module is to use an import library, provided by a .lib file. 在Windows上,链接到外部模块的传统方法是使用由.lib文件提供的导入库。 In order to do it that way, you would need to create an import library for your executable file which includes all the exported functions that your plugins need to call. 为了这样做,您需要为可执行文件创建一个导入库,其中包含插件需要调用的所有导出函数。 I've never created an import library for an executable. 我从来没有为可执行文件创建导入库。 Normally you do it for a DLL. 通常你是为DLL做的。 I'm not even sure it will work for an executable. 我甚至不确定它是否适用于可执行文件。

Some other options: 其他一些选择:

  1. Export the functions from the executable, and use GetProcAddress in your plugin to bind to them at runtime. 从可执行文件导出函数,并在插件中使用GetProcAddress在运行时绑定到它们。
  2. When you initialize the plugins, pass an interface containing all the functionality that they need. 初始化插件时,请传递包含所需功能的接口。

To call functions defined in an executable from DLL, you have to export those functions from an executable using __declspec(dllexport), just as you export functions from DLL. 要从DLL调用可执行文件中定义的函数,必须使用__declspec(dllexport)从可执行文件中导出这些函数,就像从DLL导出函数一样。

The compiler will generate an import library for the executable that includes stubs for the exported functions. 编译器将为可执行文件生成一个导入库,其中包含导出函数的存根。

Link with this import library when you build your DLL. 在构建DLL时链接此导入库。

When using mingw, this can be done by generating an import library for the executable as follows: 使用mingw时,可以通过为可执行文件生成导入库来完成此操作,如下所示:

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

The -l argument specifies the filename of the library to be created, and the -D argument specifies the dllname of the library (and it is important that this is equal to the program name). -l参数指定要创建的库的文件名, -D参数指定库的dllname(重要的是它等于程序名称)。 To compile the dll, you will then need to link against the import library by adding -l<program> to the linker flags. 要编译dll,您需要通过将-l<program>添加到链接器标志来链接导入库。

If you want to limit the exported symbols, you can first generate a defs file, edit it, and then generate the import library from the defs file: 如果要限制导出的符号,可以先生成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

Note: The name of dlltool may vary depending on the mingw environment (ie i686-w64-mingw32-dlltool on Fedora for cross-compiling to i686 windows). 注意: dlltool的名称可能因mingw环境而异(即Fedora上的i686-w64-mingw32-dlltool用于交叉编译到i686窗口)。

I had the same problem - for a proprietary app, a.exe , I wanted to build a plugin, p.dll . 我有同样的问题 - 对于专有应用程序, a.exe ,我想构建一个插件, p.dll

One post suggested: 一篇帖子建议:

$ dlltool --export-all-symbols a.exe -z a.defs
dlltool: a.exe: no symbols

But there was an a.lib file included with a.exe . 但有附带A.EXE一个A.LIB文件。 Again, no [useful] EXPORTS: 再次,没有[有用]出口:

$ 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

[see also Building a dll with a gcc using a library file (.a) converted from import library (.lib) [另请参阅使用从导入库(.lib)转换的库文件(.a)使用gcc构建dll

Eventually, finding a hint on a MinGW mailing list, nm was the solution for me: 最后,在MinGW邮件列表上找到提示, nm对我来说是解决方案:

$ echo EXPORTS >a.def
$ nm -p a.lib |egrep 'T _' |sed 's/0* T _//' >>a.def

Once you have a this .def file, it's easy: 一旦你有这个.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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从使用 Clang 编译的插件调用主要可执行文件的功能 - Call main executable's functions from plugin compiled using Clang 从共享对象中调用主可执行文件中的函数 - Call functions in the main executable from a shared object Microsoft Visual Studio:一次调试多个项目(可执行文件访问DLL中的函数+可执行文件使用的DLL) - Microsoft Visual Studio: Debugging multiple projects at once (executable that accesses functions in DLL + the DLL used by executable) 在Singleton DLL中未定义的纯虚函数 - Pure virtual functions not defined in Singleton DLL 多个Dll通过“主” dll相互调用 - Multiple Dll's calling each others functions though “main” dll 有没有办法在存储库中没有 dll 文件的情况下运行使用 SDL2 和 SDL2 映像的 C++ 可执行文件? - Is there a way to run a C++ executable that uses SDL2 and SDL2 image without having the dll files in the repository? c ++动态dll加载和加载器中定义的功能 - c++ dynamic dll loading and functions defined in the loader 如何在主可执行文件的子文件夹中部署 Qt C++ 共享库的 dll? - How to deploy a Qt C++ shared library's dll in subfolder of the main executable? 一次 included.h 函数已经在 main.obj 中定义 - One time included .h functions already defined in main.obj Qt 和可执行的 dll - Qt and executable dll's
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM