Calling Conventions in Visual Studio - c++

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

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.

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

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.

Symbol Visibility in Windows

I do a lot of programming in linux and I use the visibility attribute to define if a symbol is visible or hidden in the Shared Object. Just to make the things clearer possible: If a symbol is visible it will be accessible externally (someone linking with the shared object), if it is hidden it is supposed to be used only internally.
On windows it seems to work a bit different, it works with exporting (the symbol is defined here in the shared object and will be accessible by someone linking with this) and importing (here I am linking with a shared object and the symbol is exported there) symbols. But I couldn't find a way to tell the compiler to not export a symbol because it must be used only here, i.e. if someone link with it a linker error is expected.
My question is if I can define a symbol as "hidden" (like in linux's gcc) and how.
Also, all this visibility in windows topic is a bit fuzzy for me and I was looking for some further reading links to understand better how everything works.
David Rodriguez is correct, in the MSVC environment the programmer typically explicitly exports function/class symbols via the MSVC-specific __declspec(dllexport) modifier. Symbols that aren't explicitly exported shouldn't show up in the symbol table for the compiled DLL (you can use dumpbin, one of the Visual Studio command line utils, to verify, using the /EXPORTS option). It is convention to use dllimport when you import that symbol, although I believe this is optional. How this typically plays out is that header files defining the public interface of a DLL will have some macro that expands to __declspec(dllimport) by default, but is set to expand to __declspec(dllexport) while that library is being built.
Note that how GCC and MSVC treat dllexport may be different; perhaps GCC doesn't 'respect' dllexport in the sense of hiding unexported symbols? I would first try compiling with MSVC and test those results with dumpbin before trying the same with GCC. If you don't have Visual Studio, you can still get a MSVC compiler by either downloading VS Express, or (less known) by downloading certain .NET redistributables which ship with command line MSVC (both these options are free and legit). VS Express may be the better choice here so you can get dumpbin.

Create symbol libraries from DLLs for use with MINGW32

I'm developing an application at work using C++, Qt, Mingw32 and Netbeans. I need to use an in house API that has been developed by the software group in the company.
I have the symbol libraries .lib files for the DLLs i need to link against, but i cannot use these libs with Mingw32, it works fine with Microsoft Visual Studio.
Does anyone know if there is a way to export the symbols and create a .a symbol library that works with Mingw32 ? If not i'll have to go over to Visual Studio i guess.
I have tried using the program "pexports" to create a .def file and dlltool, but that didn't work. Still got unreferenced symbol errors, then i added the symbols it complained about to the .def, because they weren't there and it stopped complaining and compiled. But the program crashes. I tried the same code in Visual Studio and it compiles and runs fine.
Have you considered dynamically loading the DLL? LoadLibrary, GetProcAddress, etc. You can probably easily write a class that encapsulates all the DLL's entry points, loading and unloading the library, and does all the #typedefs, etc. It's grunt work but if it's an in-house library there probably aren't too many entry points?
Import libs are overrated. :p
Not sure if it helps, but you may wish to check this guide.
Here's how I did that for the mysql library.
Create a list of exports using dllwrap:
dllwrap --export-all-symbols --output-def libmysql.def libmysql.dll --implib liblibmysql.a
This creates a list of exports in the .def file but the name mangling is incorrect.
Edit the .def file in a text editor and remove the '#' symbols.
The symbol names typically also have a number appended to them as well.
I don't know how to determine the correct name except by experimentation:
Run the following to create a netbeans compatible library:
dlltool --input-def libmySQL.def --dllname libmySQL.dll --output-lib libMySQLclient.a -k
Compile with it and you'll get undefined symbols. The undefined symbols will have the correct decorations.
Edit the .def file again and correct the symbol names. Re-run dlltool to get the correct .a library file.
Have you tried linking the DLL directly, rather than a .a/.lib? MinGW is usually happy to do that for you.
I give up, some people say it is not possible with a dll compiled on microsofts compiler with c++ exports, because of the name mangling

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.