How to interface with an existing C++ Library?


#1

What’s the best way to bind to an existing native C++ library in platform independent .NET Core?

The library itself is already ported to all interesting platforms (Windows, Linux, etc…).

On “traditional” Windows .NET, we had a managed wrapper written in C++/CLI, but as far as I can see, this is not available for .NET Core on non-Windows platforms…


#2

Just make a “C” component layer. Keep all your C++ logic needed as is, then export C methods that return and take handles to the c++ class. (aka extern “C” __declspec(dllexport) void* GetClassHandle()) etc, etc

In C# just “DllImport” those methods and keep track of the handle as an IntPtr. When you need to do an operation on that handle / c++ class just pass it do a C method like “Foo(handle, “Hello World!”)”, etc, etc

I recommend porting the meat of the logic to C# and just keeping C/C++ for only the parts needed. Such as interfacing with D3D11 or some other C++ API for example.


#3

Thanks for your reply.

“Porting the meat to C#” is not really feasible. The library in question is mostly a (complex) wrapper around a set of rather complex and complicated modules mostly written in C, written for a different product with roughly a million LOC, which cannot be ported to C# for several reasons:

  • the code has strict realtime requirements
  • we need to support embedded platforms like QNX, eCos, VxWorks or Real Time Linux
  • we need to support sitting inside the kernel of Windows as a driver (due to real time requirements)
  • the code is required to run on “bare metal” with no real OS at all
  • our customers use more than 12 different families of CPUs, including strange DSPs which don’t even have a “byte” as datatype.

Thus, “porting the meat” effectively means maintaining the code in parallel, duplicating the work and thus higher risk of bugs etc

That’s why we interface it from C# using C++/CLI on “desktop .NET”.
When going to .NET Core, we wanted to avoid the hassle to “flatten” the nice object oriented interface to a plain C interface just to rebuild a nice object oriented .NET interface on top of it in C#. But it seems we need to go that way… :frowning:


#4

If you need to keep class parallel between C++ and C# you might need to make a C++ header to C# generator.

I believe this tool does that for you already: http://www.swig.org/

While I agree the loss of C++/CLI is frustrating and would be nice if there was a .net core version. SWIG might be your simplest answer.

For new projects I recommend just using the component model for most stuff.


#5

The last time I used SWIG, it generate the most unreadable code I could ever imagine so beware of that. Here is the bottom line -> Binding to C++ from C# is possible, but is a bad idea for a simple reason: name mangling.

Name mangling is something C++ compilers do to make sure that compiled symbols have unique names even if there are overloaded methods (same name), etc. The problem is there is no standard for this so each compiler does it as they see fit. So the thing you need to bind to in C# is different between Windows, Mac, Linux, etc. Furthermore, P/Invoke only allows you to bind in a C style way so it will be very unnatural, even if you can overcome this massive problem.

Bonus: These mangled names even change sometimes between compiler versions without warning.

If you are just wrapping C calls with C++ anyway, it seems like the best thing to do would be to make the same C calls via P/Invoke in C#. If that is not possible then you will need to make a C interface and use that (I’m doing the same thing right now so I wrote a script to generate the C# bindings from C headers to speed things up for me)


#6

Would it be OK for the “library” to run in a separate process? If so, consider writing a “main” in C++ that accepts commands on standard input, invokes the library appropriately, then returns results on standard output. Invoke it with Process.Start().

This has a few advantages…

  • If you need to use two such libraries, but the libraries can’t be compiled in the same address space (maybe one links to a 32-bit-only library, and one t a 64-bit-only library), you can still use both of them
  • If the library goes awry and corrupts memory or generates a segfault, your application can detect that and exit gracefully or even restart it
  • With a little more work, you could use the same parent/child protocol over a named pipe or TCP connection for network transparency

.NET Foundation Website | Blog | Projects | Code of Conduct