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

前端 未结 6 672
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-31 08:45

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

相关标签:
6条回答
  • 2021-01-31 08:51

    C++/CLI will be easier to debug if you have personnel who know how to debug C++. If you don't, it could potentially be much harder.

    I would suggest that the tradeoff here is between ease of use for the consumers of your interop assembly versus ease of maintainability for the assembly itself. If you have a solid core of senior engineers who are familiar with C++ and who can reliably maintain the assembly, it will be much easier on the rest of your team who are unfamiliar with native code to give them a fully managed interface that takes care of everything for them.

    On the other hand, if you're the only person in the shop with C++ experience, I would be very leery of embedding a C++ module into the project, in case someone else has to maintain it later.

    0 讨论(0)
  • 2021-01-31 09:11

    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.

    0 讨论(0)
  • 2021-01-31 09:11

    Think of P/Invoke as platform invocation, are you calling into something like the Win32 API which is very P/Invoke friendly or do you need to provide .NET bindings for an unmanaged library?

    Since the wrapper typically is very thin a C++/CLI wrapper doesn't necessitate that you know C++/CLI specifically. What you need to know can be found in the language specification, it's an extensive documentation with lots of examples. P/Invoke is more of an nice to have feature for smaller well established existing libraries, but if the interface for calling into that library changes you'll run into a problem. With C++/CLI you can still have a public managed interface in your C++/CLI project that's exposed for managed code and handle changes to the C API more easily that way.

    If you wanna get rid of the extra DLL you can always try ILMerge, but I'm not sure if it's capable of handling mixed assemblies, (apparently not), but it looks like it's possible to link both managed and unmanaged *.obj files with the PlatformSDK linker like this:

    cl.exe /MD /c /clr Unmanaged.cpp
    csc.exe /target:module /addmodule:*.obj Managed.cs
    link.exe /DLL /LTCG /NOENTRY /CLRIMAGETYPE:IJW *.obj Managed.netmodule
    
    0 讨论(0)
  • 2021-01-31 09:12

    For an API of this size (~40 total entry points), I would draw the dividing line between C++/CLI and P/Invoke based on how much "header file gunk" you have to duplicate in C#. If it's a small (to modest) amount, P/Invoke is fine. Once you start duplicating a lot of .H files in C#--especially for things that aren't exposed in your .NET API--you might be better off using C++/CLI.

    0 讨论(0)
  • 2021-01-31 09:14

    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.

    0 讨论(0)
  • 2021-01-31 09:14

    Lots of good answers here - another perspective is the plan for the existing C API. Arguments for using PInvoke include:

    • You need to keep a C API around for compatibility with other C consumers
    • You need to keep the code in C as it's large and migration is too expensive

    Arguments for using C++/CLI include:

    • you want to move as much of the code as possible to the CLR

    In this case you can start with C++/CLI and then move more and more over to C#

    0 讨论(0)
提交回复
热议问题