views:

2759

answers:

8

I have an interface that I have defined in C++ which now needs to be implemented in C#. What is the best way to go about this? I don't want to use COM at all in my interface definition. The way I have solved this right now is to to have two interface definitions, one in C++ and one in C#. I then expose the C# interfaces as a COM server. This was my application which is written in C++ can call into C#. Is there anyway I can avoid having to define my implementation in C++ as well as C#?

A: 

Why don't you want to use COM?

This would have been my suggestion. COM interop has worked really well for me, and I've used COM objects and interfaces in C# (simply reference the COM object and the runtime callable wrapper gets created automatically). Similarly marking a C# class as "Register for COM interop" has worked the other way around.

John Sibly
A: 

Thanks for the answer.

Can't use COM since the interface needs to be implemented in both the *nix world and Windows world.

Shao
+2  A: 

If you are willing to use C++/CLI for your managed code instead of C#, then you can just consume the native C++ interface definition directly via the header file. How easy this will be will depend on exactly what is in your interface - simplest case is something that you could use from C.

Take a look at Marcus Heege's Expert C++/CLI: .NET for Visual C++ Programmers, for a lot of helpful information on mixing native and managed C++ in .NET.

McKenzieG1
A: 

Write the interface in C++ and use macros to make it look like a standard cpp header file on UNIX and like an IDL file on windows (If this does not work out, you can always write a python/ruby script to generate the IDL from the C++ header file).

Compile the IDL to generate a typelib. Use TypeLib Importer to generate the interface definitions for C# and implement the interfaces there.

Sijin
A: 

Write the interface in IDL and use a tool to compile the interface to the target language. You might find pointers for this when looking into CORBA which was concerned with cross-language interfacing.

/Allan

Allan Wind
A: 

You don't mention which version of .NET you're using, but something that's worked for me in using Visual Studio .NET 2003 is to provide a thin C# wrapper around the pimpled implementation of the real C++ class:

public __gc class MyClass_Net {
public:
   MyClass_Net()
      :native_ptr_(new MyClass())
   {
   }
   ~MyClass_Net()
   {
      delete native_ptr_;
   }

private:
   MyClass __nogc *native_ptr_;
};

Obviously, one would prefer to use a Boost shared_ptr there, but I could never get them to play nicely with V.NET 2003...

Methods simply forward to the underlying C++ methods through the pointer. Method arguments may have to be converted. For example, to call a C++ method which takes a string, the C# method should probably take a System.String (System::String in Managed C++). You'd have to use System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi() to do that.

One nice thing about this approach is because Managed C++ is a .NET language, you get to expose accessors as properties (__property). You can even expose attributes, very much like in C#.

mlbrock
A: 

The other approach is to use a 'flat', C-style API. You might as well use extern "C" to prevent accidental overloading. Use a DEF file to explicitly name the exported functions, so they're definitely not decorated in any way (C++ functions are 'decorated' with an encoding of the parameter types in the export table).

On x86, beware of calling conventions. It's probably to explicitly declare the use of __stdcall or __cdecl. Because P/Invoke is primarily used to invoke Windows APIs, it defaults to StdCall, but C and C++ default to cdecl, because that supports varargs.

I recently wrapped the COM interface IRapiStream in a flat C interface as .NET seemed to be trying to convert the IStream into a storage, which failed with the error STG_E_UNIMPLEMENTEDFUNCTION.

Mike Dimmick
+1  A: 

Swig is a great tool for wrapping C++ classes in other languages like C#.

Jeremy