LNK2019 when converting an app to use DLLs - c++

(Re-written for clarity)
I have a multi-project solution that I am looking to convert from using .lib to .DLL files. I have created my __declspec macros and applied it to every class except for those in the project that creates the final .exe. The linker is throwing a fit on just about everything, however. I have set up to ignore errors about exporting templated objects.
One example is this:
error LNK2019: unresolved external
symbol "__declspec(dllimport) public:
void __thiscall
Rail::SetNextRail(class Rail *)"
(__imp_?SetNextRail#Rail##QAEXPAV1##Z)
referenced in function "public: static
void __cdecl
MyUtilities::CreateBezierRails(int,class
MyVector *,class std::vector > &)" (?CreateBezierRails#MyUtilities##SAXHPAVMyVector##AAV?$vector#PAVRail##V?$allocator#PAVRail###std###std###Z) MyUtilities.obj
Unresolved external symbol on my __declspec(dllimport)? That doesn't seem right. It is getting placed by a macro such as:
#ifdef MYAI_EXPORT
#define DECLSPECAI __declspec(dllexport)
#else
#define DECLSPECAI __declspec(dllimport)
#endif
Basically, what gives? Why am I getting these errors and how can I fix them? Thank you to everybody who has tried to help thus far, but I am still stuck with this.

Are you linking against MyRenderer.lib?

Do you export your functions and classes using
__declspec(dllexport)
and import them using
__declspec(dllimport)
? If not, you will have to do this. In your header, during compiling the DLL, you will need to have the dllexport clause, and when using the header in other DLLs or EXEs, you will have to use the dllimport clause. You can easily do this by defining a macro like
// set this in preprocessor options for the DLL
#ifdef MYDLL
# define MYDLL_IMPORTEXPORT __declspec(dllexport)
#else
# define MYDLL_IMPORTEXPORT __declspec(dllimport)
#endif
class MYDLL_IMPORTEXPORT MyClass {};

Well its saying that it found a declaration but no implementation. Are you sure you are compilnig the file with the function implementation in it? Have you remembered to put the MyRenderer:: before the DrawVertices call? Are you sure you are linking both the libraries into the executable?
Edit: When compiling a lib the library leaves a stub, effectively, saying I want this function when you can link it to me.
When you run the linker it runs through all the libraries looking for these stubs and "links" them to the actual implementation. Each cpp file you build compiles to an object file and this object file works in exactly the same way. If it can't link the stub to the actual function then you get a linker error such as you are seeing. Thus, either your renderer library is not being linked into the executable OR the implementation is missing something vital such as the MyRenderer::. Though if it was the latter i'd expect other problems to arise such as the lack of a IDirect3DDevice which, i assume, is a member of the class. Thus, most probably, you are failing to link the .lib in.

there are different configurations of DLLs.
staticly linked DLL - the implementations are in a DLL, and the definitions are in a .lib. You statically link to the .lib (which is kinda like a header), and the lib tells c++ how to call the function. this is probably what you want. make sure you get your __declspecs right.
dynamically linked DLL - everything is in the DLL, the definitions are also in the DLL, you need to manually set up function pointers to all the exported things, which are indexed by a string at runtime.
Google will help and made this CW so someone can make this answer suck less.
i also advise you to get DLLs working in a skeleton app.

Related

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

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.

How do I link a DLL to my project? error LNK2019: unresolved external symbol

I have a file foo.h that has various declarations for functions. All of these functions are implemented in a file foo.dll. However, when I include the .h file and try to use any of the functions, I get the error:
bar.obj : error LNK2019: unresolved external symbol SomeFunction
so obviously the function implementations aren't being found.
What do I have to do to help the compiler find the definitions in the DLL and associate them with the .h file?
I've seen some stuff about __declspec(dllexport) and __declspec(dllimport) but I still can't figure out how to use them.
You should have received at least three files from the DLL owner. The DLL which you'll need at runtime, the .h file with the declarations of the exported functions, you already have that. And a .lib file, the import library for the DLL. Which the linker requires so it knows how to add the functions to the program's import table.
You are missing the step where you told the linker that it needs to link the .lib file. It needs to be added to the linker's Input + Additional Dependencies setting of your project. Or most easily done by writing the linker instruction in your source code:
#include "foo.h"
#pragma comment(lib, "foo.lib")
Which works for MSVC, not otherwise portable but linking never is. Copy the .lib file to your project directory or specify the full path.
I just had a similar problem. The solution turned out to be that the DLL was 64 bit, and the simple app using it was 32. I had forgotten to change it to x64 in the Configuration Manager.
You need to specify in front of function definitions __declspec(dllexport) keyword at the time of building the dll
You need to import or load the .dll file into process memory.
You need to acquire the address of function you want to use from that dll.
Some useful links to get started:: MSDN Documentation, SO, Random

How do I fix an Unresolved External Symbol error in my C++ DLL?

I have a dll, which accesses some classes outside of its project (I'm using Visual Studio, so I have two projects). The thing is, in the header that the dll includes, which is outside of the dll's project, there are only bodies of functions, like this:
x.h
class x
{
void myFunc();
}
And in another cpp file, outside of the dll file:
#include "x.h"
x::myFunc()
{
//.....
}
The dll is only getting the bodies of the functions, so when I compile, I get lots of unresolved external symbols (I'm quite sure that this is the issue, because I tested with another class fully built in a .h file, in another project, and no errors). So how can I solve this mystery?
It is normal for the import headers to only have function signatures; the actual function bodies are already compiled into the DLL binary and are resolved at link time by linking into the actual DLL.
The first thing to try is to make sure you are actually linking to the said DLL. It isn't enough to just include the header, you also need to link to the binary. So in your project configuration, you need to add a link to (for example) the .lib file that gets created along-side the DLL when the DLL is compiled (if in MSVC). This lib file lets the linker know how to connect the function signatures you included via the import header to the actual implementations contained in the DLL. If you're on a different platform, the mechanics might be a little different, but the concepts will be similar.
Edits:
The next step is to make sure the binary is actually exporting the symbols you're trying to link against. Make sure that all interface signatures are being exported via __declspec(dll_export) prefixes. Normally this is wrapped up in an IFDEF so that the header is declared export while the DLL is being compiled, but not when that header is included in a client project. Next, you could use dumpbin to check the mangled export names, and see if there is anything unexpected.
Here's a modified version of your example that illustrates this style of export (note, I haven't tested if this compiles, apologies for any typos):
#ifdef BUILDING_MYDLL
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
class MYDLL_API x
{
void myFunc();
}
You would then set your configuration to define BUILDING_MYDLL when compiling the dll, but not when compiling the executable. This way the functions are only marked export when compiling the library dll. Now you can mark your public API functions with MYDLL_API and they should get exported during build.
Please note that dll_export, dll_import, and declspec are all very MSVC-specific constructs. Other compilers/runtimes handle symbol export in different ways.
There's multiple ways to link DLL into your app on Windows, check out this existing question/answer:
https://stackoverflow.com/a/2060508/1701823

Not all symbols of an DLL-exported class is exported (VS9)

I'm building a DLL from a group of static libraries and I'm having a problem where only parts of classes are exported.
What I'm doing is declaring all symbols I want to export with a preprocessor definition like:
#if defined(MYPROJ_BUILD_DLL)
//Build as a DLL
# define MY_API __declspec(dllexport)
#elif defined(MYPROJ_USE_DLL)
//Use as a DLL
# define MY_API __declspec(dllimport)
#else
//Build or use as a static lib
# define MY_API
#endif
For example:
class MY_API Foo{
...
}
I then build static library with MYPROJ_BUILD_DLL & MYPROJ_USE_DLL undefined causing a static library to be built.
In another build I create a DLL from these static libraries. So I define MYPROJ_BUILD_DLL causing all symbols I want to export to be attributed with __declspec(dllexport) (this is done by including all static library headers in the DLL-project source file).
Edit:
Note on unrefenced symbols: Linker options Keep Unreferenced Data (/OPT:NOREF) and Do Not Remove Redundant COMDATs (/OPT:NOICF) is set so that no unreferenced symbols will be removed.
Ok, so now to the problem. When I use this new DLL I get unresolved externals because not all symbols of a class is exported. For example in a class like this:
class MY_API Foo{
public:
Foo(char const* );
int bar();
private:
Foo( char const*, char const* );
};
Only Foo::Foo( char const*, char const*); and int Foo::bar(); is exported. How can that be? I can understand if the entire class was missing, due to e.g. I forgot to include the header in the DLL-build. But it's only partial missing.
Also, say if Foo::Foo( char const*) was not implemented; then the DLL build would have unresolved external errors. But the build is fine (I also double checked for declarations without implementation).
Note: The combined size of the static libraries I'm combining is in the region of 30MB, and the resulting DLL is 1.2MB.
I'm using Visual Studio 9.0 (2008) to build everything. And Depends to check for exported symbols.
Edit:
For the ones who wonder why I don't just build a DLL from each of the static libraries: I can't because they cross-reference each other (that's why I need to group them together in one a single DLL). I know, it's horrible I can't really understand the logic behind it.
Remember that when you link against a static LIB, by default the linker is only pulling in the functions, classes, and data that the client (which in this case is your DLL) actually references.
So what happens is this:
You build your static LIB, and that's fine. This LIB is 100% valid.
You now build your static DLL around the original binary LIB. It pulls in only the stuff that it actually references. It doesn't pull in the entire class definition which is what it needs to do. This DLL, though it builds, is invalid.
A client then uses the DLL, and expects to see a complete binary definition for the exported class, because that's what the client sees in the accompanying header file.
However the class has only been partially imported, and this is why you're getting those link errors.
To fix:
If you're able to, don't build your DLL off your static LIB. Build your DLL off the original source code. And build your static LIB off the original source code.
Otherwise you can possibly fiddle with linker settings but I strongly recommend option 1 above. Note that OPT:NOREF won't work here as OPT:NOREF has no effect on static LIBs.
What wont't fix it:
High-level linker tweaks like OPT:NOREF, anything involving COMDATs, etc. If you want those functions present, you have to make sure they're referenced, either by referencing them, or by telling the linker explicitly, "hey, this Symbol X is referenced".
As a side note:
Anytime I build a DLL or LIB, I build both a DLL and a LIB, using exactly the technique you're using. Having a single code base that can generate either a DLL or a LIB by toggling a setting is ideal. But building a DLL off of a (binary) static LIB when you own the source code for both... I'm having a hard time imagining when such a scenario would be necessary.
The problem is surely that you use the already-built static .lib in your DLL project. That cannot work, you have to rebuild the .lib so that the functions get the __declspec(dllexport) declarator and will be exported by the linker.
At that point, it just isn't all that useful anymore to create the DLL compatible version of the .lib in the first place. Just create two projects, one that creates the static .lib, another that creates the DLL. Technically it is possible to still use the static .lib in your DLL project but you'll have to export the functions with a .def file. That can be high maintenance if the library has a lot of exports.
This is probably years too late, but OP's complaint was that a private method (the destructor) was not exported from a dllexport'd class. Isn't that normal? No external user is allowed to call a private method.

LNK2019 problem

I have a LNK2019 problem when trying to use some DLL in my project.
Details:
I have a DLL project called dll1; that compiled just fine (using __declspec(dllexport)) in order to export the class inside dll1 (for dll2 usage).
I have another DLL project dll2 that uses dll1's functionality. I specified the *.dll1.lib file path inside the linker input in the project's properties and gave reference to dll1 *.h files. At this point everything needs to work fine. (I think..)
When compiling dll2, I get a LNK2019 error that tells me can't find some method referenced in dll1. (This method in dll1 is a static method.)
Why do I get this error?
The MSDN page about LNK2019 already gives plenty of examples why this error occurs. In order to trace down what exactly is going on, I recommend doing this:
Run undname on the symbol which the linker complains about to demangle the name (see Viewing Decorated Names for an example how to run undname).
Run dumpbin /EXPORTS (or use the graphical Dependency Walker) to get a list of all symbols exported by DLL1.
So now you have the demangled name of the symbol which the linker tries to find, and you have the list of symbols which are exported by DLL1. And the linker tells you that it cannot find the requested symbol in the list. Here are two ideas about what's going on:
You see that DLL1 has the demangled symbol in its export list, but not exactly the mangled name which the linker complains about. This can happen when the function you export is almost the same which the linker expects. It might be that you have a 'const' missing somewhere, or the calling convention is different.
You see that DLL1 doesn't export any symbol which looks like what the linker expects. This suggests that some __declspec(dllexport) is missing in the declarations of DLL1.
For regular static class methods the declspec(dllexport) should be sufficient but in some cases (inline friend functions for example) you need to provide declspec(dllexport) for the function.
e.g.
#define DLLEXPORT __declspec(dllexport)
class DLLEXPORT A {
A();
int somefunc();
DLLEXPORT friend int operator==(const A &ws1, const A &ws2)
{ /* some code */ }
};
Just a guess:
If you include the header from dll1 in the dll2 project and in that header you use the __declspec(dllexport)) you tell the linker that dll2 is also exporting these classes that actually are meant to be imported by dll2 and so is missing classes definition.
So one would ususally use a definition like this.
#ifdef DLL1_EXPORTS
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT A
{
//...
This construction makes sure, the dll1 definitions are exported when the header is used in dll1 and imported when used inside dll2 project. All you need is the macro DLL1_EXPORT to be defined when dll1 is compiled. The project settings for dll1 is usually a good place.
Another approach is to have 2 different headers, one for building dll1 and a second to be used together wit dll1's lib (without any __declspec(dllexport)).
I recently had the same problem. The problem was a method signature void myMethod(const MyType&);with a parameter which I had forward-declared as class MyType;; however, the definition was a struct MyType{};.
As described in https://stackoverflow.com/a/40738415/71051 this can lead to linker issues with Visual-C++ - in my case the LNK2019.
Took me a while to resolve this, maybe this is of help for someone in the future.