1

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

Marcus Campbell
  • 2,746
  • 4
  • 22
  • 36
DSS
  • 53
  • 1
  • 8
  • 1
    Do you want to use the libraries [statically or dynamically](https://stackoverflow.com/questions/140061/when-to-use-dynamic-vs-static-libraries)? – GKE Sep 12 '18 at 05:25
  • I am happy to use any way. What is prefer way of doing it in C++/CLI project? I am trying to use static way by using .lib file but getting weird LNK2005 error. error LNK2005: "public: virtual char const * __cdecl std::exception::what(void)const " (?what@exception@std@@UEBAPEBDXZ) already defined in .... – DSS Sep 12 '18 at 05:27
  • How is your library compiled and how are you currently trying to link it? Without seeing your code my best guess is that you compiled it statically and are trying to link it dynamically. As for the preferred way of doing it in a C++/CLI library, I'm pretty sure that's dependent on you and your needs, if i recall correctly there is no preferred way, as long as you aren't trying to dynamically link against a statically compiled library or vice versa. – GKE Sep 12 '18 at 05:35
  • The library is provided by third party. They provided both .lib file as well as .dll file. Isn't .lib file is statically compiled library and .dll is dynamically library? Or I am missing something here and getting confused? – DSS Sep 12 '18 at 05:38
  • A .lib is static and a .dll is dynamic, how exactly are you trying to link one of them? You **cannot** use both. – GKE Sep 12 '18 at 05:40
  • I am trying to do static way and updated the question above about what I did so far and what problems I am having. Is there anything I missed which is resulting in linking errors? – DSS Sep 12 '18 at 05:44
  • 1
    You're getting these errors because you're trying to statically link a C++ library into a C# program. Have you [tried making a Managed C++ Wrapper?](https://social.technet.microsoft.com/wiki/contents/articles/40194.managed-c-wrapper-for-unmanaged-code.aspx) prior? – GKE Sep 12 '18 at 05:50
  • Don't forget that a statically linked library (.lib) means that they get "embedded" into your program, that means no .dll files in the end program. Try do the instructions I linked. – GKE Sep 12 '18 at 05:52
  • Thats what I am doing. Created Managed C++ wrapper project (CLR). Sorry about the confusion. – DSS Sep 12 '18 at 05:53
  • If it didn't work, then try dynamically linking it, I'm fairly certain you have to use `DllExport` in order to do so. If it works, then your wrapper is faulty. – GKE Sep 12 '18 at 05:59
  • 1
    I think the only way to answer this question would be to write a thorough **tutorial** and you should probably google for some. (That's not to say it's necessarily OT, but you'll probably be faster finding a real tutorial than waiting for someone to write it up here.) – Martin Ba Sep 12 '18 at 06:38
  • [Using c++ library in c#](https://stackoverflow.com/questions/772041/using-c-library-in-c-sharp) , [how to use c++ libraries(.lib) in c# WPF project](https://stackoverflow.com/questions/43116241/how-to-use-c-libraries-lib-in-c-sharp-wpf-project) , [Presenting a C++ library (.lib) for use in C# project](https://social.msdn.microsoft.com/Forums/vstudio/en-US/299da822-5539-4e5b-9ba7-b614e564c9f4/presenting-a-c-library-lib-for-use-in-c-project?forum=vcgeneral) , [Call C++ library in C#](https://stackoverflow.com/questions/574801/call-c-library-in-c-sharp) – GKE Sep 12 '18 at 07:13
  • I could not make linking error go away after trying everything mentioned in various links. – DSS Sep 12 '18 at 23:00
  • You dug yourself into a *really* deep hole by trying to fix an earlier compile or link error. The exception::what() method is always a `__thiscall` function, an instance function on the exception class. But the linker says `__cdecl`. That is never correct. Worse, it is never correct multiple times, what the linker is complaining about now. You must rewind to the original problem, what you did about it is completely wrong. – Hans Passant Sep 12 '18 at 23:30
  • Hi Hans, I have not done a lot. I have updated the problem description above telling what I did. I got this error when I include header file from 3rd party in CLR project. I have not written any code to use the library yet. – DSS Sep 22 '18 at 02:44

2 Answers2

5

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:

  1. Turn off CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS.
  2. Export/import explicitly the desired symbols from the DLL (using __declspec(export|import).
0

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.

ADG
  • 343
  • 1
  • 9
  • The third party library I am using in shared library. It meant to link on load time. I got header files, .lib file which is DLL import library and .DLL file. All I did so far is below:- 1. Set 'Additional Inlcude Directories' in C/C++ so that we can find include files. 2. Set 'Additional Library Directories' in linker->General option. 3. Set name of lib in 'Additional Dependencies' in Linker->Input setting. When I include the third party header file in my project, I get this LNK2005 error I mentioned above. Not sure whats going on!! – DSS Sep 21 '18 at 23:08
  • Did you check what compiler the vendor used to build their shared library. Did you try to link a simple C++ command line test program? – ADG Sep 22 '18 at 01:09
  • They are using CMake 2.8 to generate the libraries. I cannot see dllexport/import in header files of the libraries but it seems new feature of cmake allow you to export functions without having you to specify dllexport/import. The build file shows they are using "Visual Studio 15 2017 Win64" to build it. I tried to unsuccessfully link it using both visual studio 2015 and 2017. It link fine without CLR support. Does that tell us anything? I have a feeling that they are missing something but I am not sure what as I dont know anything about building libraries using cmake. – DSS Sep 22 '18 at 01:36
  • Ok, so they built it with VS 2017 (15 is the version number for VS 20170). The fact that it build without CLR support suggests you are using a compatible compiler but there is an issue with your CLR configuration. Are you building you CLR dll in 64bit mode? Are you using the /MD flag when building your C++ code? – ADG Sep 22 '18 at 01:47
  • Yes. I have set the platform to x64. And flag is also set to /MD which is default when I created clr project. Setting any other flag results in incompatible error. – DSS Sep 22 '18 at 01:54