2

I heard somewhere that all Windows .DLLs must contain definitions for every symbol it references, so a .DLL file like this would never compile since it doesn't implement bar().

void bar();

__declspec(dllexport)
void foo() {
    bar();
}

I think the analogy is that .DLLs are essentially executables with a different entry point, so they have to have all referenced defined, like an executable.

But in a Unix environment, I can compile this to a .so file with no problem. I can then use dlopen(path, RTLD_NOW | RTLD_GLOBAL); from the host application to load the library and merge the host's symbols with the library's. If the host defines bar(), the library will simply call that function.

I can't just re-define everything into the .DLL file, because in my application the library uses thousands of symbols from the host. Using MinGW or possibly Visual C++, is there really no way to use a symbol from the host by leaving it undefined in the .DLL and merging it when loaded? I don't want to set thousands of callback functions in the .DLL either, because that gets difficult with C++ methods.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Vortico
  • 2,610
  • 2
  • 32
  • 49
  • 2
    You heard wrongly. A Windows DLL can use a symbol from the executable that loads it, though it's a little unusual. You just export the function from the executable (e.g., using `__declspec(dllexport)`) and import it into the DLL (e.g., using `__declspec(dllimport)`). – Harry Johnston Sep 28 '16 at 23:26
  • ... although now that I think of it, I don't know whether MinGW supports doing this. I don't see why it *wouldn't*, but I don't know. – Harry Johnston Sep 28 '16 at 23:27
  • I'm willing to use Visual C++ if needed, but I'm just happy that this is possible. I'm rereading how `dllimport` works because I must have misunderstood something last time. – Vortico Sep 28 '16 at 23:30
  • Depends what you're reading. I imagine most writers aren't going to bother covering this stuff. Even the documentation doesn't mention it explicitly as far as I know. – Harry Johnston Sep 28 '16 at 23:35
  • _"I heard somewhere that all Windows .DLLs must contain definitions for every symbol it references"_ Where did you hear that? We need to correct the source of that misinformation. Can you imagine if every DLL needed to contain a definition for every standard library symbol it used? Nonsense! – Lightness Races in Orbit Sep 29 '16 at 00:44
  • @LightnessRacesinOrbit This isn't where I originally heard it, but it says it pretty directly here. http://edll.sourceforge.net/ *"As many people may know, DLLs have one limitation: they cannot have even one undefined symbol."* Assuming this is correct, how am I misunderstanding this? – Vortico Sep 29 '16 at 00:56
  • 1
    An undefined symbol means a symbol that isn't either present in the source code *or in one of the object files you are linking against*. That includes import libraries. The article goes on to explain how to create an import library for your executable, exactly as in your self-answer, although the author claims that this is "kind of cumbersome" for reasons that escape me. – Harry Johnston Sep 29 '16 at 01:39

1 Answers1

6

I figured out how to do it with MinGW.

Usually, when linking DLL files (e.g. plugin.dll), you export a list of symbols to libplugin.a, but in this case, I actually want to export the symbols from the host executable host.exe to libhost.a.

x86_64-w64-mingw32-g++ -o host.exe host.cpp -Wl,--out-implib,libhost.a

This generates the symbol list, which you can link to when building your plugin.

x86_64-w64-mingw32-g++ -shared -o plugin.dll plugin.cpp -L. -lhost

This builds the DLL using the libhost.a file (in the current directory ".").

Now, it's a bit annoying to fill your host code with __declspec(dllexport), so you can add the --export-all-symbols linker flag. And for some reason, it doesn't seem to require _declspec(dllimport) attributes either after doing this, but I don't know why. So, you can compile the host with

x86_64-w64-mingw32-g++ -o host.exe host.cpp -Wl,--export-all-symbols,--out-implib,libhost.a

Vortico
  • 2,610
  • 2
  • 32
  • 49
  • See http://stackoverflow.com/a/4490536/886887, the `__declspec(dllimport)` isn't necessary but allows the linker to optimize the calls. (Although since MinGW compiles and links in a single command, perhaps you get the optimization for free too.) – Harry Johnston Sep 29 '16 at 00:39
  • For the benefit of future readers, note that the (potential) downside to exporting all symbols rather than specific ones is that it means that a third-party plugin might use an internal symbol or function you hadn't intended to make available, potentially causing compatibility issues down the track. If you're only dealing with your own code this doesn't matter - although in that case it is usually simpler to use static linking rather than having a DLL at all. – Harry Johnston Sep 29 '16 at 02:13
  • It's a good solution. But I really think the way for windows with mingw to build a DLL is ugly. – Jimmy Jun 09 '17 at 02:25