How do I use a C++ library from C# and .NET?

2019-03-29 13:40发布

问题:

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.

回答1:

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



回答2:

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)


回答3:

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.



标签: c# .net c++ dll