trouble linking to de-decorated DLL names in C++ (32 bit) in Visual Studio
Asked Answered
M

0

2

I have a library of DSP functions in C++ and I want to link to them dynamically at run time. I am using the PDLL.h method to wrap my classes (for example FFT) into C-style functions and load them load on the fly in other C++ applications. I want to use these functions in .NET applications and COM components, so I have to use __stdcall which decorates the names in 32 bit builds.

In order to undecorate the names, I am using the trick mentioned here: C++ DLL Export: Decorated/Mangled names (wqw's answer, 2nd down). So for example, in my library's .h file I have declared my wrapped functions so:

#pragma comment(linker, "/EXPORT:DoFFT=_DoFFT@12")
RTLIBS_API DoFFT(FFT* x, DOUBLE* pdDataIn, DOUBLE* pdDataOut);

This does indeed work, and when I look into the dll with dependency walker, I see that there is both an entry for DoFFT and _DoFFT@12.

The problem that I have is that when I try to build a project that links to this library (dynamically, at run time, not using the .lib file at all) I get linker errors for all the functions in my dll, i.e.:

Error   31  error LNK2001: unresolved external symbol _DoFFT@12 

I don't understand why this is happening. First of all, the symbol _DoFFT@12 does exist (according to dependency walker) and second of all, why is the linker looking for it in the first place? I am linking to it at run time, not at compile time so how does my project even know about this symbol?

All the functions are declared with the same chain of macros that reduces to (e.g.):

extern "C" __declspec(dllexport) int __stdcall DoFFT(FFT* x){...}

Nothing having to do with the library is declared on the client side.

Marlowe answered 18/8, 2017 at 8:17 Comment(9)
Even if you use dynamic linking, you still need a .lib file (symbols only, no code) to make the connections to the dll.Florettaflorette
Even when using LoadLibrary? (see e.g. en.wikipedia.org/wiki/…)Marlowe
For this linker error to happen you have to be declaring extern DoFFT and then calling it in your test project. Try starting with an empty project and make sure LoadLibrary/GetProcAddress approach is working there.Conflagration
@Conflagration I tried this and the same linker errors occur. I added some information about function definitions in the op.Marlowe
Use a module file, not linker comment pragmas.Interblend
Well, the linker is convinced that your code is not doing it dynamically. It is never wrong about that. Consider using the /verbose linker option, helps to see which .obj file contains the reference to the function. Do consider that you might be helping too much, a [DllImport] declaration already does all of this.Cookhouse
@HansPassant I tried using the /verbose linker option. The first and only mention of _DoFFT@12 is when the linker error occurs, so this didn't end up telling me much. But maybe I'm looking for the wrong thing. Again, I don't understand this. My theory is that when I build my client, the C++ compiler sees the function definitions in the library header and then the linker assumes that they will be decorated. Then, the client doesn't find the decorated symbols in the DLL. So, how to dismantle this behavior. However, if my theory is correct then wqw's method doesn't ever work (which is false).Marlowe
That tells you a lot. If you don't see it in the /verbose trace then the only other ways to force the linker to look for a symbol is with a .def file or the /export option. Oh, wait, looks like you did :) Delete the #pragma, it is poison when it is #included by client code. If necessary use a .def file to force renamed exports. And note that it isn't necessary, you can just as easily provide the decorated name when you use GetProcAddress().Cookhouse
@HansPassant: Aha! This makes sense now. So, as I suspected, my theory about VC was incorrect. In the hope that I can get a bitdepth-independent set of DLL function names that clients can call without knowing the name decorations and without my meddling with a .def file, I tried moving the #pragmas into the function definitions (.cpp file) rather than the header. This generates the undecorated names sure enough, but my test client somehow doesn't find them. .def is def-initely the way to go (for my particular design specs on this particualr project).Marlowe

© 2022 - 2024 — McMap. All rights reserved.