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

Ian G picture Ian G · Apr 1, 2010 · Viewed 10.5k times · Source

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 be 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 an 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 differ noticeable 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 inter-op problem, is this true?
  • Language familiarity enough people know C# and C++ but knowledge of details of C++/CLI are rarer here.

Anything else?

Answer

JaredPar picture JaredPar · Apr 1, 2010

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.