.dll Plugin that uses functions defined in the main executable
Asked Answered
G

4

6

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?

Ginny answered 16/3, 2013 at 21:36 Comment(5)
Can you share at least the interface header of the plug in ?Savarin
interface: privatepaste.com/c6118a7e85 example_plugin: privatepaste.com/dd152f6c64 session->Send() == void session::Send(CString str) {...send something via socket...}Ginny
I've posted the header directly in the question, it seems the header is ready to roll from Windows POV ...Savarin
Yep, the header works, the session->Send() is the problem, the vs linker crys "undefined reference"Ginny
Hey, I know this is old: what solution did you end up using? Did making an import library for the executable work for you? Or did you end up using one of the other solutions proposed by @DavidHeffernanHelsie
A
5

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.
Aerostatic answered 16/3, 2013 at 21:42 Comment(0)
C
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).

Cao answered 9/8, 2013 at 13:27 Comment(5)
Hello, does this approach work for you? I'm getting error code 127 when loading the plugin using LoadLibrary.Helsie
It works here on my msys2's mingw64 shell, but when using --export-all-symbols option, there are too many symbols exported in the .a file. In my exe file, I only have the symbols need exported by __declspec(dllexport) decoration, so the option --no-export-all-symbols is used instead to let the lib<program>.a file has those limited symbols.Promethium
Sorry, I just checked the output .a file, and it looks like it's empty. So I need a way to generate a .a library which contains all the __declspec(dllexport) marked symbols.Promethium
Under msys2 mingw64, I found a better way to do this, first, download(install) this: https://packages.msys2.org/package/mingw-w64-x86_64-tools, and use the tool gendef and genlib tools. The first tool will generate a def file from the exe or dll file, and the second tool will create the .a import library.Promethium
It looks like genlib does not generate the correct .a file, I have to use the dlltool instead, this is the command I use the generate import file dlltool --dllname exe_export.exe --def exe_export.def --output-lib libexe_export.a.Promethium
C
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.

Corrugate answered 18/3, 2013 at 2:12 Comment(0)
O
1

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
Ordonez answered 13/11, 2014 at 9:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.