[thread] on_tls_prepare in win32\tss_pe.cpp incompatible with static linkage to a /clr object

I'm very interested in being able to have a native C++ executable which makes use of boost's TSS and also be able to wrap .NET modules with C++/CLI (i.e. /clr). And I much prefer it to be statically linked. The C++/CLI wrappers work fine when they are dynamically linked, but they cause a runtime initialization error (0xc000007b) whenever they are connected in only static links. It doesn't matter whether the host executable is compiled with /clr or not - somehow the MSVC linker knows to add some CLR initialization voodoo to the PE header whenever a static link to a /clr-enabled object is made. And that PE header voodoo seems to be incompatible with some of boost::thread's own brand of PE header voodoo which appears to be intended to provide TLS support for Windows. But as far as I can tell, I was able to get TLS working with MSVC9 even after commenting out the on_tls_prepare lines in tss_pe.cpp - commenting out the other lines wasn't necessary:
#if (_MSC_VER >= 1400) //#pragma section(".CRT$XIU",long,read) #pragma section(".CRT$XCU",long,read) #pragma section(".CRT$XTU",long,read) #pragma section(".CRT$XLC",long,read) static __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback; // static __declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare; static __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init; static __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term; #else
I put together a test case that I'm pretty sure shows that TLS still works without that function. At the very least, can there be some preprocessor define to manually disable it for CLR compatibility? Or perhaps there is a way to adjust this voodoo to be compatible with the CLR initialization? I'm hosting the test case at: http://fenchurch.mc.vanderbilt.edu/files/TLS_CLR_Test.7z It includes a main function which runs a test of the TSS semantics, and a CLR class which tests console output via C++/CLI. I included binaries and the boost_thread.lib files for both the broken and "fixed" versions of tss_pe.cpp. Thanks, Matt Chambers

The C++/CLI wrappers work fine when they are dynamically linked, but they cause a runtime initialization error (0xc000007b) whenever they are connected in only static links.
I had a similar problem when I tried to use boost within a CLR program. When I rebuilt the boost libraries with the /CLR option, the problem went away. There is a thunking layer that takes place between managed and unmanaged code. If you statically link managed code with unmanaged code, the link will take place just fine and fool you into believing the program is going to run. But at runtime, the CLI tries to load and link the pieces of the code together, and when it fails, it aborts with the 0xC000007b error. Building the boost libraries with the /CLR option makes boost managed-code as well. You may want to have two sets of boost libraries. One set for C++ applications, and another set for CLI applications. -Sid Sacek

Hi Sid, I tried what you said to get around the 0xc000007b error by building boost with /clr, but that didn't work for me. It's also a pretty heavy solution (requiring all of boost to be managed) when my alternative seems to work fine (allowing to disable the on_tls_prepare initialization function). Thanks, -Matt Sid Sacek wrote:
The C++/CLI wrappers work fine when they are dynamically linked, but
they
cause a runtime initialization error (0xc000007b) whenever they are connected in only static links.
I had a similar problem when I tried to use boost within a CLR program. When I rebuilt the boost libraries with the /CLR option, the problem went away.
There is a thunking layer that takes place between managed and unmanaged code. If you statically link managed code with unmanaged code, the link will take place just fine and fool you into believing the program is going to run.
But at runtime, the CLI tries to load and link the pieces of the code together, and when it fails, it aborts with the 0xC000007b error. Building the boost libraries with the /CLR option makes boost managed-code as well.
You may want to have two sets of boost libraries. One set for C++ applications, and another set for CLI applications.
-Sid Sacek
participants (2)
-
Matthew Chambers
-
Sid Sacek