views:

370

answers:

3

I'm currently in a project that need to work both on Mac and Windows. We are using standard portable C++ for all the application logic. However, since we want the app to feel totally native on both platform, the GUI will be written with C#/WPF for Windows and Objective-C/Cocoa for Mac.

However, for the windows part, I am wondering what is the best way to use the C++ code with C#. C# is managed, and I know that we can use managed C++ too. However I worry that using C++ inside the CLR may introduce unexpected bugs, or that we will need to put an awful lot of #ifdef WIN32 everywhere in the C++ code to make it work both with the managed CLR and the unmanaged environnement of Mac OS X (note that we sure expect to put some ifdef, but we'd like to keep it under control if possible). So basically, what is the best way to use the C++ code with the C# code? Right now, I'm thinking of three solutions

1- Compile the C++ as C++/CLI and directly use the classes and function from C#.

2- Compile and wrap the C++ in an unmanaged win32 dll and call it from C# using DllImport

3- Wrap the C++ in a COM wrapper and use the .NET COM Interop to link it with C#

Which one is the best way? Or, if there is a better solution, what is it?

+3  A: 

C++/CLI has several restrictions over standard C++ that don't always make it easy to recompile standard C++ as C++/CLI. Keep in mind that you'll have to distinguish 'managed' and 'unmanaged' pointers, for starters. As these are using different symbols, you've got your first set of #ifdefs right there. And then you get to ref and value classes and all that sort of fun.

You can however use C++/CLI to bridge the gap between native code and the .NET world. The last time I did something along the lines of what you're planning to do, I used C++/CLI to write the bridging layer that did the necessary translation and conversion work between .NET types and classes and the native world. The C++/CLI layer can obviously be used from any .NET language.

You can't always use (2) - this depends very much on the data types you're trying to exchange between the two worlds. The .NET marshalling code is pretty good at dealing with C PODs but anything more complicated and you've got a problem.

(3) is overkill IMHO and introduces another point of failure, plus you're then doing .NET <-> COM <-> native instead of the simpler .NET <-> native if you created your own bridging code. Not to mention that you add complication to your code that won't benefit the other OS you're targeting, namely OS X.

Timo Geusch
+1  A: 

Our development team has been using C++/CLI compiled code with ASP.NET and WPF front ends for while now.

The first major issue we had was build time. The code base would be 150k lines (40+ projects) and took forever to link (due to linker issues we could not build the individual projects as DLL's). We were only able to resolve this issue by wrapping the code with managed C++ classes and building our projects as assemblies.

The second major issue was performance. We originally compiled with /clr (before pure option existed) and this resulted in double thunking of most of our calls that occurred in the managed C++ layer. We fixed this by switching to /clr:pure. By doing so we ran into an issue where our assemblies resulted in having too many 'global' methods in the assemblies so they would not load. We had to split our assemblies further to solve this issue.

karmasponge
A: 

Best and easier way is to do it with .NET <-> COM because COM has much stronger bridge compared to native dll access inside .NET because it may lead to lots of memory issues and lots of troubleshooting time. Its easier to test COM inside any MFC project and get the trace information for debugging and when the component is ready it can be easily used inside .NET.

CLI will not let you use all features and unfortunately its fairly new so less documentation is available and you will not get good support for your questions.

Win32 dll and DLLImport has problems mainly to troubleshoot, because the exception thrown inside Win32 dll will not travel further along the stack instead it will simply crash and you will not get the reason. Where else in COM you can catch exception internally and the COMException thrown inside .NET will not crash your entire application.

COM will be little slower in performance, but it will be more organized and good design pattern to develop.

Akash Kava