[solved] Using Boost in C++/CLI and C# mixed code environment
Hi! With the help of Anthony Williams and Hansi plus a step by step fiddling with the Visual Studio settings I finally managed (sic!) to get C++ and Boost playing nicely in a mixed C++/CLI plus C# code setting. Phew. Went to hell and came back again. Disclaimer: This document was written in order to be useful and published in the hope that it is helpful to others. There is no guarantee that this information really helps in all similar settings. Maybe things are still broken deep inside, but my little demo application at least does not choke on startup or finalization anymore. If you have additional insight, please share this information. Contact me by mail and/or followup to this post. So here is a summary of what I found out: I create a solution containing a C++/CLI project and a C# (Google: CSharp) project, which references the C++/CLI project. The C++/CLI project is a DLL-project which uses the Boost libaries. Without any further settings, the autolink features of Boost are configured such that the Boost libraries are statically linked to the C++ DLL (which IMHO normally is fine and exactly what I want: no extra libraries to ship with my software). Note that some libaries may be used implicitly: Spirit for example includes Boost.Threads when BOOST_SPIRIT_THREADSAFE is defined. Alas, the default compiler settings may lead to trouble: Statically linking to Boost libraries may yield an executable which chokes on startup with a System.BadImageFormatException, even if the compiler and linker run without warning (a bug, IMHO). Explanantion: <cite author="Anthony Williams" date="2009-02-04 15:54:40 GMT"> The problem is that the static boost thread library tries to hook the native win32 PE TLS callbacks in order to ensure that the thread-local data used by boost thread is cleaned up correctly. This is not compatible with a C++/CLI executable. </cite> Solution: In Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions add BOOST_ALL_DYN_LINK in order to force the usage of the DLLs. In addition copy the necessary DLLs to the directory where the executable resides. E.g. copy boost_thread-vc90-mt-gd-1_XX.dll to MyApp/bin/Debug. It also helps to #define BOOST_LIB_DIAGNOSTIC in the Preprocessor Definitions to find out from the compiler output which libraries are to be included. The .NET framework throws a System.IO.FileNotFoundException on missing libraries without further information about which files are missing (The classical Mirosoft way to handle these things since Windows 98: "An error has occurred.") Setting these compiler flags should yield an application that does not fail on startup. Enters the next bug of Visual Studio: The C++/CLI compiler deliberately chooses to ignore the #pragma managed(push, off) / #pragma managed(pop) PREPRO directives for files which are compiled with /clr command line flag. You obtain a plethora of warnings of the form warning C4793: 'boost::[..]::`vcall'{0}'' : function compiled as native : For the executable this means that on termination another exception is thrown, which adds to the confusion: Unhandled exception at 0x7c812a7b in XXX.exe: 0xC0020001: "Die Zeichenfolgenbindung ist unzulässig." or in english: Error 1700 "The string binding is invalid" or RPC_S_INVALID_STRING_BINDING. Solution: Put managed (CLI) and unmanaged C++ code into different compilation units. For unmanaged code files change the compiler settings this way: In "Configuration Properties -> C/C++ -> General -> Compiler with Common Language" support choose "No Common Language Support". Now things should work fine. best regards, Markus
participants (1)
-
Markus Werle