tags:

views:

123

answers:

3

My question is closely related to how a DLL exports C++ classes and generic methods (wrt C++ language features without a C# parallel).

I believe you can call functions inside an extern "C" block from C# by just referencing the DLL and using DLLImport. But can you instantiate a templated C++ type? What if the C++ type does somethin' crazy that's not supported in C#? Is there an RFC or relevant part of the C# specification?

Thanks...

EDIT: I now stumbled across P/Invoke which should be valuable, but I'm still looking for a specification or standard regarding this.

+5  A: 

The sane way to do it is to use managed c++ to access unmanaged c++ and compile into an assembly.

iterationx
Any more information on this? I'm new to Windows programming, I'm used to Unix, static linking, and Makefiles... How do I create a managed DLL or unmanaged DLL with C++ in VS2010?
Robert Karl
@robert http://ondotnet.com/pub/a/dotnet/2004/03/29/mcpp_part3.html
iterationx
@robert the link above exposes the very old outdated managed C++ syntax, `__gc` becomes `ref` in the modern syntax for example.
jdehaan
Check this link at the bottom the differences between syntax are showed i nice examples: http://www.visualcplusdotnet.com/visualcplusdotnet18b.html
jdehaan
+2  A: 

I believe you can call functions inside an extern "C" block from C# by just referencing the DLL.

Wrong, you have to use DllImport or so-called PInvoke (Platform Invoke) to call a native C function from managed code. Referencing works only for .NET assemblies or COM with an automatically generated interop dll.

Using C++ from C# becomes a real nightmare because of name mangling among other things.

If you can you could compile a managed C++ Dll as a wrapper to make both worlds meet. This has also the advantage that you can mark your assembly as ComVisible, thus making it available to plenty of tools capable of handling COM.

An alternative is to write a C wrapper around the C++ API, what can be tedious and ugly.

EDIT:

Help to decide which approach to use:

  • 1) You have a native C dll
    • WARNING: if you use a .lib from Managed C++, then the dll is not truely dynamically linked and cannot be replaced with a simple drop in of a newer compatible version.
    • PREFERRED: Use P/Invoke from any .NET language (drop-in replacement possible)

  • 2) You have a native C++ dll
    • DO NOT use P/Invoke, this is a real nightmare (because of name mangling among other things)
    • PREFERRED: Build a wrapper .NET dll with managed C++, works only if you have a compiler compatible with the one that was used to compile the native dll.
    • If the native DLL was build with an incompatible compiler (Compiler A) of the one you can use for managed C++ (Compiler C), then I advise to build (With the same compiler A) a C wrapper around the native C++ dll. Then use the P/Invoke method to use this wrapper C dll like described in 1)
jdehaan
thanks for the correction. can you create a .NET assembly with C++?
Robert Karl
Yes you can but with Managed C++ which is not actually C++ but will let you link against native C++ Dlls if you happen to use the same compiler than the guys that generated the pure C++ dll you are using.
jdehaan
P/Invoke is not fun
iterationx
No it really isn't :-). But a good way to truely dynamically link against 3rd party C dll from .NET. With Managed C++ is too easy to taint the pure .NET world with native stuff.
jdehaan
A: 

What the DLL does internally is irrelevant, as far as C# is concerned. Keep in mind that C++ templates do not generate any code until the template is instantiated. If the template is simply defined somewhere in the DLL header files, then there won't be any generated code for that template in the DLL. On the other hand, if the DLL explicitly instantiates and exports some templated types, then you could theoretically call them from C#.

There are two issues you'd have to overcome. The first is that C++ compilers mangle their method names, so you'd have to figure out exactly what the proper name to PInvoke is. The second problem is that there's no way to create CRT objects in C# directly. You'd have to define some factory methods and export those as well.

Frankly, I think this is all way more trouble than its worth. You'd be better off creating a C-style API for the DLL and calling those functions from C#. Internally, the functions could create and manipulate the relevant C++ objects.

Peter Ruderman
OK, it sounds like a giant pain. Creating a C API is a fair solution, but I'm surprised there isn't a more flexible interop mechanism...
Robert Karl
The interop mechanism would have to handle all possible mangling schemes for any compiler as there is no standard for this (that's a big pain) and marshalling/unmarshalling is not trivial. In the case of COM everything is specified in interfaces and types are well defined in terms of size and alignment.
jdehaan