Mixed-Mode library assembly bug

S

Steve Terepin

I've found some rather worrying articles (Mixed Mode Library Assembly bug,
Richard Grimes, Windows Developer Network Sept 2003 ; and Knowledge Base
Article 814472 ) that point out the need to use the /noentry switch and an
explicit initialisation procedure, to be able to safely use Managed C++
assemblies that call down into standard C library functions.

Could someone confirm that I've understood this properly ? I'm writing some
Managed C++ code that provides a wrapper around some existing native C++
code that makes use of the standard C library and also invokes routines in a
3rd-party LIB. This code will be built into an assembly that will be called
from a front-end GUI written in C#. Therefore, I *do* need to follow all the
guidelines in 814472, and explicitly call an initialisation function from my
GUI app. Yes ?

Given that this is the case, is there a way of having the initialisation
code automatically invoked when the assembly is loaded ? Relying on client
code to call the initialisation function seems rather ugly :-(

Steve.
 
B

Bart Jacobs

Steve said:
Could someone confirm that I've understood this properly ? I'm writing some
Managed C++ code that provides a wrapper around some existing native C++
code that makes use of the standard C library and also invokes routines in a
3rd-party LIB. This code will be built into an assembly that will be called
from a front-end GUI written in C#. Therefore, I *do* need to follow all the
guidelines in 814472, and explicitly call an initialisation function from my
GUI app. Yes ?

That is indeed what it says in KB 814472.
Given that this is the case, is there a way of having the initialisation
code automatically invoked when the assembly is loaded ? Relying on client
code to call the initialisation function seems rather ugly :-(

You can avoid all of this ugliness by not using mixed DLLs in the first
place. You can write a pure native Win32 DLL that wraps your C++ code
and exposes it as a P/Invoke-friendly flat API. For example:

==== CppLibrary.DLL ====================================================

__declspec(dllexport) class MyClass {
public:
MyClass(int x) { ... }
~MyClass();
void DoStuff();
};

==== End CppLibrary.DLL ================================================

==== Wrapper.DLL =======================================================

extern "C" __declspec(dllexport) MyClass *CreateMyClass(int x) {
return new MyClass(x);
}

extern "C" __declspec(dllexport) void DeleteMyClass(MyClass *myClass) {
delete myClass;
}

extern "C" __declspec(dllexport) void MyClassDoStuff(MyClass *myClass) {
myClass->DoStuff();
}

==== End Wrapper.DLL ===================================================

==== C# Client =========================================================

class MyClass : IDisposable {
[DllImport("Wrapper.DLL")]
extern static IntPtr CreateMyClass(int x);

[DllImport("Wrapper.DLL")]
extern static void DeleteMyClass(IntPtr myClass);

[DllImport("Wrapper.DLL")]
extern static void MyClassDoStuff(IntPtr myClass);

IntPtr handle;

public MyClass(int x) {
handle = CreateMyClass(x);
}

public void Dispose() {
DeleteMyClass(handle);
}

public void DoStuff() {
MyClassDoStuff(handle);
}
}

==== End C# Client =====================================================

Advantages of this approach:
- no mixed DLLs, ergo no mixed DLL bugs
- no need for explicit initialization
- transparency: no It Just Works magic or surprises
- easier to see where managed-unmanaged transitions occur, which is
important for performance

Advantages of mixed DLLs (a.k.a. It Just Works):
- type fidelity between managed and unmanaged worlds:
- static type checking
- native data structures can be accessed as usual in managed functions

Good luck!

Bart Jacobs
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top