C++ .dll adding in Visual Studio - yet another "unresolved external symbol" - c++

I am adding .dll to C++ project.
IDE: Visual Studio 2013
What I did:
Added directory with headers to VC++ Directories -> Include Directories
. It's ok, I can include headers, IntellySense sees names
in these files.
Added .lib file to Additional Dependencies section and a path to this
file in both VC++ Directories -> Library Directories and Linker -> General -> Additional Library Directories.
Placed actual .dll file to DEBUG folder (also to project folder, just
to be sure)
Used dumpbin.exe to get sure I have exported all needed classes in my
.dll
And I still get a bunch of unresolved externals with functions stored in that .dll. Any suggestions?
I found this question and set Use library Dependency Inputs to Yes. Still no luck.
Some more info:
Error example:
Error 2 error LNK2019: unresolved external symbol "__declspec(dllimport) public: double __thiscall Fem::Node::GetX(void)" (__imp_?GetX#Node#Fem##QAENXZ) referenced in...
This function in dumpbin output:
172 AB 000F81A0 ?GetX#Node#Fem##QEAANXZ
I see some difference in the last part of the name. Somehow, as I mentioned in the comments, I got it working in Qt project with Visual Studio compiler.

This is usually a bad idea, since it doesn't lead to a reusable library. The application can't be rebuilt with a new compiler or even new compile settings without also rebuilding the DLL. It is safer to just compile the classes you use in statically. That said, there are some benefits if used in conjunction with delay-loading, so...
In order to store a class implementation in a DLL, while building the DLL you must use __declspec(dllexport) on the class, and when consuming it there must be __declspec(dllimport). Import libraries have shims to forward free function references to DLLs but those don't work for classes and class members.
Usually macros are used to accomplish the switch between dllexport and dllimport.
Now that you've shown mangled names, the difference becomes apparent, and demangling gives a clue to where the problem came from.
Linker is looking for
public: double __thiscall Fem::Node::GetX(void)
But DLL is exporting
public: double __cdecl Fem::Node::GetX(void) __ptr64
Notice that the calling conventions are different; if this had linked, you would have crashed as soon as you tried to call this function.
You cannot use exports from a DLL that have C++ signatures from an application compiled differently. Are you mixing architectures (x86 vs x86_64 vs ARM)? Can't do that either, not even using highly-compatible C calling signatures.

Related

Linking error while in C++/CLI project while wrapping C++ shared library

I am trying to wrap C++ library to that managed projects can use it. The third party library I am using is a shared library. It's meant to link on load time. I have header files, .lib file which is DLL import library and .DLL file.
This is what I did so far:-
1. Created CLR project.
2. Added path for header file in C/C++->General->Additional Include Directories
3. Set 'Additional Library Directories' in Linker->General.
4. Added lib name in Linker->Input->Additional Dependencies
After I do that, I get LNK2005 linking error followed by LNK1169. The only thing I did after creating the project is including header file from C++ library which I am trying to wrap. What am I doing wrong?
error LNK2005: "public: virtual char const * __cdecl std::exception::what(void)const " (?what#exception#std##UEBAPEBDXZ) already defined in ...
fatal error LNK1169: one or more multiply defined symbols found
Indeed, we were the creators of the library and after a long battle, we were able to figure out the issue. In case it's useful for somebody else, here goes the answer.
The library was being generated using CMake, and to avoid having to export symbols by hand (using __declspec(export), we simply turned on
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS on)
However, doing that in a DLL implies that Visual Studio not only exports the symbols defined in the DLL itself, but also in its inherited dependencies (like the entire STL for example).
The previous (I'm not really sure why) is not a problem is you are linking this library as part of the building of an executable (as we do have a C++ EXE that successfully uses this DLL), but it's a major issue if you are linking the DLL against another DLL (which is the case for CLI/C++, where you're basically creating one DLL to wrap another DLL). In the latter, the CLI DLL will also try to import the symbols from the system, resulting in the redefinition previously displayed:
error LNK2005: "public: virtual char const * __cdecl std::exception::what(void)const " (?what#exception#std##UEBAPEBDXZ) already defined in ... fatal error LNK1169: one or more multiply defined symbols found
One way to check this is to take a look of the export file (.def) generated by the base C++ DLL (not the CLI one), it contains std::exception::what (among many others), although that DLL never defined it by itself.
So the solution was rather simple:
Turn off CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS.
Export/import explicitly the desired symbols from the DLL (using __declspec(export|import).
You are probably trying to link statically two different versions of the standard library. Have you checked with the third party provider of the library to determine what version of Visual Studio/C++ they used to build this library?
Also, when troubleshooting issues with third party libraries, you should try to link a simple command line executable before you try to build a C++/CLI library.
And yes, if possible you should statically link the native C++ library to your C++/CLI dll. It will make deployment easier. Presumably this will be the only C++/CLI assembly your C# app will use.

Calling Conventions in Visual Studio

I have a fortran DLL built in the CVF convention and my c++ code built using cdecl calling convention to get the stuff it needs from my DLL. I checked in my c++ code obj files and the symbols are '_imp_variable'. Then in my fortran dll the symbol shows up as 'variable'. I got some linker errors (unresolved external symbol _imp_variable), is it because c++ is looking for '_imp_variable' exactly as is in my DLL? Or does VS cdecl calling convention just adds stuff weirdly but it knows to look for 'variable'?
Prefix __imp__ is added by __declspec(dllimport) storage-class attribute. It means that object or function is imported from DLL using import library (usually created by linker on DLL build). Make sure you added such library to your project.
If for unknown reason you don't have import lib or DLL sources take a look here: http://support.microsoft.com/kb/131313

C++ Project compiles as static lib, fails (linker error) as dynamic lib. why?

I've a VS2008 native C++ project, that I wish to compile as a DLL.
It only references one external library (log4cplus.lib), and uses its functions.
(also uses log4cplus's .h files , naturally).
When I try to compile my project as a static library, it succeeeds.
When I try as DLL, it fails :
1>MessageWriter.obj : error LNK2019: unresolved external symbol "public: static class log4cplus::Logger __cdecl log4cplus::Logger::getInstance(class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> > const &)" (?getInstance#Logger#log4cplus##SA?AV12#ABV?$basic_string#_WU?$char_traits#_W#std##V?$allocator#_W#2##std###Z) referenced in function "class log4cplus::Logger __cdecl Log(void)" (?Log##YA?AVLogger#log4cplus##XZ)
There are 4 more errors just like this related to functions within log4cplus.lib.
It seems like something really stupid.. please help me :)
Thanks!
Edit :
I am linked against the log4cplus.lib file, and it finds it just fine.
also, the log4cplus.lib is 100% functional, I am using it in another project with no problems.
My original intention was to compile my project as a static library and use it in another DLL I am writing, but when do this, I get the same linker errors in that other project...
Edit #2 :
The functions which cause the linker errors are static functions.. could this be part of the problem?
wilx is right.I have the same link problem.
it took me almost one day to slove this issue.
I have downloaded log4cplus-1.0.4, after I opened this project with visual studio 2010,compile it, both static and dynamic library, no error.
however, when I try to use those library, I got a link error,no matter static library or dynamic library.
the reason is,by default, those project use multi-byte character, however, my own project use unicode,so,to slove those link problem, you just need to change one project's charset.
both unicode or both multi-byte charset.
and to change one project's charset in visual studio 2010,
see the following link.
How do I turn off Unicode in a VC++ project?
When you're creating a static library, the library creator does not try to resolve all the functions that you are using (the ones that are in log2cplus.lib). These functions are resolved when you create an executable that links with your static library.
When you're creating a dynamic library, the library creator (the linker) does try to resolve all the functions you are using. You have to provide the linker with the log4cplus.lib library as soon as you build the dynamic library. You cannot wait until you create the executable.
In either case you need to link against library.
Difference is that when you link statically - all functionality is linked via library you're using.
When you're linking dynamically you link against import library which have functionality to load and use functions from dll and this step you're missing. Usually import library have the same name as the dll you're linking against.
Edit:
I saw it that missing symbol is not '__imp...'
This means that header file is not "configured" for dynamic linkage, probably because you have LOG4CPLUS_BUILD_DLL or log4cplus_EXPORTS or DLL_EXPORT not defined in project where you include Log4Cplus headers.
Are you actually linking with the log2cplus.lib file? If you were compiling as a static library then you would link to it via the final .exe and not in the static library - perhaps that is the difference?
Did you use __declspec(dllimport) and __declspec(dllexport)?
They are not necessary when linking static libraries, but required for DLLs. The function has to be declared for exporting (in the DLL), so users can use it outside (and thus import it from the DLL).
Maybe this can help:
Importing into an Application Using __declspec(dllimport)
http://msdn.microsoft.com/en-us/library/8fskxacy%28VS.80%29.aspx
best regards
If you're using a compiler like MSVC, then it may have changed the project settings without you knowing about it when changing from lib to dll. You should double-check that in DLL mode, you are properly linked to the lib.
There are two possibilities that I can see for the linker error:
You have compiled the log4cplus.dll (and the associated log4cplus.lib import library) using the provided Release build configuration but now your application is compiled with "Character Set" option set to "Use Unicode Character Set"
Or you are trying to use log4cplus' static library but defining LOG4CPLUS_BUILD_DLL for your application.
I bet on number 1. It could be something else, still. What version of log4cplus are you using?
If you want to use log4cplus.dll in your application, define the LOG4CPLUS_BUILD_DLL symbol. log4cplus_EXPORTS and DLL_EXPORT are there only to support the CMake based build system, and autotools based build system on MingGW respectively.

C++ Linking problem

I have an error in compiling a project.
I'm trying to link to a library I have on windows, using visual studio.
When trying to create the obkect (with new), I get the following error:
Error 2 error LNK2005: "public: __thiscall std::basic_string,class std::allocator >::~basic_string,class std::allocator >(void)" (??1?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##QAE#XZ) already defined in RMLibV053.lib(Inifile.obj) msvcprtd.lib
I used #ifndef
I used disable warning
It may be that your code is set up to use a different run-time environment (single-threaded, multi-threaded, multi-threaded DLL) than your PTLibV002.lib library when it was built.
If PTLibV002.lib was compiled to use C++ library statically linked and your binary uses C++ library as DLL, then this is the linking error you'd receive. This is because PTLibV002.lib will contain the definitions of functions from STL it uses, and your binary contains another definition pointing to the C++ library DLL.
probably you added a similar library to additional libraries.
As Ferruccio explained before.
I used on the visual studio configuration of project: compiled with the setting to use the dynammic linked run time library : Multi-threaded Debug DLL (/MDd) instead of Multi-threaded Debug (/MTd).

Best practices for debugging linking errors

When building projects in C++, I've found debugging linking errors to be tricky, especially when picking up other people's code. What strategies do people use for debugging and fixing linking errors?
Not sure what your level of expertise is, but here are the basics.
Below is a linker error from VS 2005 - yes, it's a giant mess if you're not familiar with it.
ByteComparator.obj : error LNK2019: unresolved external symbol "int __cdecl does_not_exist(void)" (?does_not_exist##YAHXZ) referenced in function "void __cdecl TextScan(struct FileTextStats &,char const *,char const *,bool,bool,__int64)" (?TextScan##YAXAAUFileTextStats##PBD1_N2_J#Z)
There are a couple of points to focus on:
"ByteComparator.obj" - Look for a ByteComparator.cpp file, this is the source of the linker problem
"int __cdecl does_not_exist(void)" - This is the symbol it couldn't find, in this case a function named does_not_exist()
At this point, in many cases the fastest way to resolution is to search the code base for this function and find where the implementation is. Once you know where the function is implemented you just have to make sure the two places get linked together.
If you're using VS2005, you would use the "Project Dependencies..." right-click menu. If you're using gcc, you would look in your makefiles for the executable generation step (gcc called with a bunch of .o files) and add the missing .o file.
In a second scenario, you may be missing an "external" dependency, which you don't have code for. The Win32 libraries are often times implemented in static libraries that you have to link to. In this case, go to MSDN or "Microsoft Google" and search for the API. At the bottom of the API description the library name is given. Add this to your project properties "Configuration Properties->Linker->Input->Additional Dependencies" list. For example, the function timeGetTime()'s page on MSDN tells you to use Winmm.lib at the bottom of the page.
One of the common linking errors I've run into is when a function is used differently from how it's defined. If you see such an error you should make sure that every function you use is properly declared in some .h file.
You should also make sure that all the relevant source files are compiled into the same lib file. An error I've run into is when I have two sets of files compiled into two separate libraries, and I cross-call between libraries.
Is there a failure you have in mind?
The C-runtime libraries are often the biggest culprit. Making sure all your projects have the same settings wrt single vs multi-threading and static vs dll.
The MSDN documentation is good for pointing out which lib a particular Win32 API call requires if it comes up as missing.
Other than that it usually comes down to turning on the verbose flag and wading through the output looking for clues.