.dll Plugin that uses functions defined in the main executable

99封情书 提交于 2019-12-30 10:04:20

问题


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.

The plugin uses functions like session->SendLine("bla") which are defined in the Main executable. (class of session ans methods defined in a .h included in the plugin, but the actual function in a .cpp compiled in main exec).

tl;dr: "I need the windows linker to ignore undefined references in plugins, defined in the main executable"

What is the best way to "make it work" in windows but keep it compatible with Linux without a million #ifdef's?


回答1:


Linking of libraries on Windows is handled completely differently from how it is handled on Linux. Linking from plugin to host executable is simple on Linux, but not so much on Windows.

On Windows the traditional way to link to an external module is to use an import library, provided by a .lib file. 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. 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.
  2. When you initialize the plugins, pass an interface containing all the functionality that they need.



回答2:


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.

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.




回答3:


When using mingw, this can be done by generating an import library for the executable as follows:

$ 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). To compile the dll, you will then need to link against the import library by adding -l<program> to the linker flags.

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:

$ 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 (i.e. i686-w64-mingw32-dlltool on Fedora for cross-compiling to i686 windows).




回答4:


I had the same problem - for a proprietary app, a.exe, I wanted to build a plugin, 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. 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)

Eventually, finding a hint on a MinGW mailing list, nm was the solution for me:

$ 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:

$ #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


来源:https://stackoverflow.com/questions/15454968/dll-plugin-that-uses-functions-defined-in-the-main-executable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!