tags:

views:

146

answers:

2

So I'm architecting an application that does necessarily C++ work, but MFC/ATL is too messy for my liking, so I had this brilliant idea of doing all the "thinking" code in native C++ and all the pretty UI code in C#. The problem, though, is interoperability between the two of them. Before I get too carried away with this, I was wondering if this is a solved problem, and there's a really good way to do this. Note that I don't want to mix logic and display in the same module, as it gives rise to annoyingly high coupling.

Here's what I have so far - http://i50.tinypic.com/2gy5ctv.png

So tell me, can it be done better?

+8  A: 

The easiest way to handle this is to use C++/CLI, and expose your logic as .NET types.

It's very easy to wrap a native C++ class in a ref class that's usuable directly from a C# user interface.

That being said - this was my plan, originally, in my current project. My thinking was that I'd need the native code for some of the heavy math work we typically do. I've found, however, that it's been easier, faster, and nicer to just move most of my logic directly into C# (separated from the UI code, but still in a C# assembly) rather than try to implement it in C++.

My experience has been that speed has not been an issue - unsafe C# code has nearly always managed to be as fast or faster than the equivelent C++ when tuned, and it's easier to profile and tune the C# code.

Reed Copsey
So is the wrapper code I placed in Proxy.dll is pretty much this same strategy? Can I take this as a "looks good to me"?
Clark Gaebel
As far as the .NET/C++ interface part of your diagram goes, yes, it looks good. I've done this same sort of thing whith an existing C++ code base where I wanted to do the GUI in C#.
AaronLS
I too have re-written C code into C# and been very satisfied with the performance I have seen. It would have to be a very processor intensive application not to notice it.
Jeffrey Cameron
Even very processor intensive C++ can be faster in C#, surprisingly enough.... @wowus: Yes. You can wrap your native API (proxy.dll?) in one or more ref class instances, and access them directly from C#. It works great.
Reed Copsey
I'm just using Proxy.dll as a container for all the wrapping code so neither of the modules has to know about the others existence.
Clark Gaebel
A: 

You may have a good reason for your core to be a DLL. But it isn't necessary. I've had success with an application that is C++, it creates an App Domain and loads an assembly into it, then instantiates an object in the app domain and calls it, passing it an interface to the application. This is basically what the C-runtime does when you make an unmanaged app anyway.

The interface that the C++ code exposes to the C# code is defined in C#. I think this is easier than defining the intefaces in pure COM. C# interop gives you more control of the marshalling than C++ does.

  • create a file app_interface.cs that defines the interface
  • compile app_interface.cs into a dll, we don't care about the dll. we need the type library.
  • in the C++ code #import <app_interface.tlb> raw_interfaces_only this turns the typelib into a C++ .h file with interface definitions: app_interface.tlh
  • Implement the interfaces

You can sprinkle your app_interface.cs with attributes that control the marshalling like this

[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("ffffffff-ffff-ffff-ffff-ffffffffffff")] // guid changed from what I really use 
public interface IMyHostApplication
{
   ...

   void   AddErrorDetails (
      [MarshalAs(UnmanagedType.Error)] uint hr, 
      [MarshalAs(UnmanagedType.LPWStr)] string  szErrDetails);

   ...
}
John Knoeller
I'd like to separate the C++ code from the C# code as much as possible, keeping the surface area to a minimum. Also, I don't want to think about managed code while I'm doing native.
Clark Gaebel
The main point is that when starting from scratch it's easier to define the inteface between the two parts in C# right from the start. #import gurantees that what C++ and C# see as the interface definition both come from a single file.
John Knoeller
No matter how you do this, you should definitely try an minimize the surface area of the interface between C++ and C#
John Knoeller