views:

42

answers:

2

What's the best way to do this....?

I have some Native C++ code that uses a lot of Win32 calls together with byte buffers (allocated using HeapAlloc). I'd like to extend the code and make a C# GUI...and maybe later use a basic Win32 GUI (for use where there is no .Net and limited MFC support).

(A) I could just re-write the code in C# and use multiple PINVOKEs....but even with the PINVOKES in a separate class, the code looks messy with all the marshaling. I'm also re-writing a lot of code.

(B) I could create a native C++ DLL and use PINVOKE to marshal in the native data structures. I'm assuming I can include the native C++ DLL/LIB in a project using C#?

(C) Create a mixed mode DLL (Native C++ class plus managed ref class). I'm assuming that this would make it easier to use the managed ref class in C#......but is this the case? Will the managed class handle all the marshaling? Can I use this mixed mode DLL on a platform with no .Net (i.e. still access the native C++ unmanaged component) or do I limit myself to .Net only platforms.

One thing that bothers me about each of these options is all the marshalling. Is it better to create a managed data structure (array, string etc.) and pass that to the native C++ class, or, the other way around?

Any ideas on what would be considered best practice...?

UPDATE: I know I can re-write the native C++ code from scratch, but it means duplicating the code and prevents me from easily reusing any code updates with any Win32 application. What concerns me most is the best way to marshal the various data between the managed and unmanaged world. To me, a mixed mode DLL looks like the most flxible option, but I'd like to get a different perspective on the potential pitfalls.

+1  A: 

Why not just use .NET directly? It seems to me like your problem arises from the fact that you are dependent on the original native library, but you don't mention that it can't simply be re-done in .NET.

As for .NET-native interop, PInvoke is messy, but it does work. I'd go with that if you can't change the original DLL into .NET.

DeadMG
A: 

Option C gives you the least work if the marshaling turns out to be simple and easy for the framework to handle (is everything blittable?). It also gives you a place to hook in your own marshaling. I wrote something about this ages ago marshaling between date types etc but I think today I would write a marshal_as<> overload between your managed and native types. It would be the most elegant solution and also the least code.

Update: found my old article - it was for PInvoke. http://codeguru.earthweb.com/columns/kate/article.php/c4867/

Kate Gregory