Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

P/Invoke or C++/CLI for wrapping a C library

We have a moderate size (40-odd function) C API that needs to be called from a C# project. The functions logically break up to form a few classes that will comprise the API presented to the rest of the project.

Are there any objective reasons to prefer P/Invoke or C++/CLI for the interoperability underneath that API, in terms of robustness, maintainability, deployment, ...?

The issues I could think of that might be, but aren't problematic are:

  • C++/CLI will require a separate assembly; the P/Invoke classes can be in the main assembly. (We've already got multiple assemblies, and there'll be the C DLLs anyway, so not a major issue.)
  • Performance doesn't seem to differ noticeably between the two methods.

Issues that I'm not sure about are:

  • My feeling is C++/CLI will be easier to debug if there's an interop problem; is this true?
  • Language familiarity - enough people know C# and C++, but knowledge of details of C++/CLI are rarer here.

Anything else?

like image 242
Ian G Avatar asked Apr 01 '10 16:04

Ian G


People also ask

What is CLI wrapper?

Zigbee CLI wrapper (zb_cli_wrapper) is a Python package for the nRF5 SDK for Zigbee that includes a wrapper for automating communication with the Zigbee CLI Agent example and improving the control of the Zigbee network. It is a standalone package and can be used on both Windows and Linux machines.

What is C++ CLI wrapper?

C++/CLI Wrapper As previously mentioned, this is the link between the C# class and the main C++ application. This project was created using the empty CLR Class project in Visual Studio. Once the project is created, a header and source file were added. A reference to C# class library dll was also added to the project.

Can you use C libraries in C#?

C Libraries compiled for Windows can be called from C# using Platform Invoke. From MSDN, the syntax of making a C function call is as follows: [DllImport("Kernel32. dll", SetLastError=true)] static extern Boolean Beep(UInt32 frequency, UInt32 duration);


2 Answers

In the case where I am working with an existing C library, I prefer PInvoke. PInvoke, while a bit tedious and troublesome at times, is a fairly well understood technology that has an ever growing set of tools and internet documentation available. Generally speaking, whatever problem you run into, there is already a sample available on the web, or a quick check on stack overflow will provide a solution.

C++/CLI is a great technology, but IMHO its documentation is limited as compared to PInvoke for interop specific scenarios. It also doesn't have the tooling infrastructure for interop solutions that PInvoke has. Adding a C++/CLI assembly for a scenario that can be solved with PInvoke just seems too costly to me.

On the other hand, if I'm working with a large C++ library, I consider C++/CLI a bit more. PInvoke does not work with C++, and I must end up adding some kind of intermediate layer. Either a small C layer to wrap all of the C++ function calls or a C++/CLI library to bridge the gap. C++/CLI feels a bit more natural to me in this case.

like image 190
JaredPar Avatar answered Sep 25 '22 00:09

JaredPar


It depends in large part how memory ownership is handled. P/invoke can marshal pointers only when memory management is one of a couple particular ways, usually caller-allocated buffers. If your API returns pointers (via return value or out parameter, doesn't matter) and expects them to be handed back to a destruction function later... p/invoke will either do the automatic marshaling or give you direct access to the pointer value you need to send back later, never both. So C++/CLI becomes a very desirable approach in that case.

like image 25
Ben Voigt Avatar answered Sep 25 '22 00:09

Ben Voigt