Boost logo

Boost Users :

Subject: [Boost-users] [solved] Using Boost in C++/CLI and C# mixed code environment
From: Markus Werle (numerical.simulation_at_[hidden])
Date: 2009-02-10 04:35:22


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


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net