tags:

views:

184

answers:

7

Is there a way to write an object in C/C++ that can be used from .NET? I would like to do it in a most simple way, the one used to extend basically all other languages, i.e. write an object in C, conform to the interface required by the language runtime, use the object from the language.

A: 

You can make a library in C/C++ and export the methods and use it in .NET by using P/Invoke.

Wael Dalloul
+3  A: 

If you use managed C++, that compiles to IL code, so that can be used straight of in any .NET language.

For unmanaged C/C++ code, you need to use P/Invoke in the .NET code to call it.

Guffa
P/Invoke is extremely inefficient as I am passing large binary BLOBs as arguments and P/Invoke would require copying it.What I need is an access to .NET infrastructure from my component, so that I can access the data without need to copy it. Managed C++ provides this kind of thing, however, I would like the thing to work with both .NET and Mono and managed C++ is not supported with Mono :(
In other words: Is there a JNI-like interface for CLR?
If you want it to work in Mono, I'd try the PInvoke approach and check to see whether performance is acceptable before spending additional time looking for a more elegant approach.
Programming Hero
@martin: Have you actually tried it? I've moved some pretty big arrays back and forth with no problems at all, especially when I'm performing an operation like matrix-matrix multiplication with complexity near O(n³) while the copying is only O(n).
280Z28
A: 

You need to use C++/CLI (formerly called Managed C++, but that term is I think deprecated by the marketing boys at Microsoft).

C++/CLI is a C++ superset which compiles to .NET IL and provides features to allow interoperation with other .NET languages.

C++/CLI allows mixed managed and native code. It is the only .NET language that supports that.

Clifford
+1  A: 

If P/Invoke or C++/CLI are not suitable for your task you can use COM support in .NET.

Here's a sample for it:

C++ part

C# part

It works on both MS.NET and Mono.

elder_george
A: 

Two ways:

C++/CLI: C++/CLI is one method that makes things bridgeable. Classes that you create for CLI in C++/CLI are not exactly regular old C++ classes but you can bridge C++ classes with Adapter patterns (watch for those SEHExceptions!)

P/Invoke: If you want to develop using basic native C/C++ libraries, you can access any standard C export from the CLR using P/Invoke and you can Marshall your objects over manually if you declare them right on both sides. See the "Interop with Native Libraries" guide for more information that you could ever want to know.

I can't stress it enough. Watch your exceptions! Don't let them escape from your CLI code into your native code or from your native code into their CLI code.

Zac Bowling
A: 

If you're working with unmanaged types (ECMA-334 §27.2), an example being arrays of primitive types, you can do the following. As this sacrifices quite a bit of code safety, I highly recommend trying alternatives first and only resorting to this if the P/Invoke proves slow in release builds outside the debugger (the debugger uses a much slower P/Invoke (100x slower) to catch several kinds of failures).

[DllImport("NativeLibrary.dll")]
private extern unsafe void NativeMethod(byte* data, int length);

byte[] data = new byte[10000000];
unsafe
{
    fixed (byte* ptr = data)
    {
        NativeMethod(ptr, data.Length);
    }
}
280Z28
A: 

Mono cannot currently compile C++/CLI, unfortunately, so while C++/CLI is probably the most efficient and straightforward way to do what you're asking, it's probably not going to work for you. You could compile the C++/CLI assembly with the .NET tools, perhaps, but even that may not work well (scroll down to the answer about "Can I execute my Visual Studio .NET program...").

P/Invoke or COM interop should do it, although P/Invoke carries with it potential performance issues and COM interop means you need to turn your previously-simple vanilla C interface into a COM interface... which, in C, isn't that pleasant.

Josh Petrie