P / Invoke o C++ / CLI para envolver una biblioteca de C


Tiene una API C de tamaño moderado (función de 40 y pico) que necesita ser llamada desde un proyecto de C#. Las funciones se dividen lógicamente para formar unas cuantas clases que serán presentadas por API al resto del proyecto.

Hay razones objetivas para preferir P / Invoke o C++ / CLI para la interoperabilidad debajo de esa API, en términos de robustez, mantenibilidad, implementación,...?

Las cuestiones que podría pensar que podrían ser, pero no son problemáticas son:

  • C++ / CLI requerir un ensamblado separado, las clases P / Invoke pueden estar en el ensamblado principal. (Ya tenemos múltiples ensamblajes y habrá las DLL de C de todos modos, así que no es un problema importante).
  • El rendimiento no parece diferir notablemente entre los dos métodos.

Los problemas de los que no estoy seguro son:

  • Mi sensación es que C++/CLI será más fácil de depurar si hay un problema entre operaciones, ¿es cierto?
  • Bastante familiaridad con el lenguaje la gente conoce C# y C++ pero el conocimiento de los detalles de C++ / CLI son más raros aquí.

¿Algo más?

Author: Ian G, 2010-04-01

6 answers

En el caso de que esté trabajando con una biblioteca de C existente, prefiero PInvoke. PInvoke, aunque un poco tedioso y problemático a veces, es una tecnología bastante bien entendida que tiene un conjunto cada vez mayor de herramientas y documentación de Internet disponible. En términos generales, cualquiera que sea el problema con el que se encuentre, ya hay una muestra disponible en la web, o una comprobación rápida del desbordamiento de pila proporcionará una solución.

C++ / CLI es una gran tecnología, pero en mi humilde opinión su documentación es limitada en comparación con PInvoke para escenarios específicos de interop. Tampoco tiene la infraestructura de herramientas para soluciones interop que tiene PInvoke. Agregar un ensamblado C++/CLI para un escenario que se puede resolver con PInvoke me parece demasiado costoso.

Por otro lado, si estoy trabajando con una gran biblioteca de C++, considero C++/CLI un poco más. PInvoke no funciona con C++, y debo terminar añadiendo algún tipo de capa intermedia. Ya sea una pequeña capa de C para envolver toda la función de C++ llamadas o una biblioteca C++/CLI para cerrar la brecha. C++ / CLI se siente un poco más natural para mí en este caso.

 15
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-27 21:52:24

Depende en gran parte de cómo se maneja la propiedad de la memoria. P / invoke puede ordenar punteros solo cuando la administración de memoria es una de un par de formas particulares, generalmente buffers asignados por el llamante. Si su API devuelve punteros (a través del valor devuelto o el parámetro out, no importa) y espera que se devuelvan a una función de destrucción más tarde... p / invoke hará la clasificación automática o le dará acceso directo al valor del puntero que necesita enviar más tarde, nunca ambos. So C++ / CLI se convierte en un enfoque muy deseable en ese caso.

 7
Author: Ben Voigt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-02 01:17:17

Piense en P/Invoke como invocación de plataforma, ¿está llamando a algo como la API Win32 que es muy amigable con P/Invoke o necesita proporcionar enlaces. NET para una biblioteca no administrada?

Dado que la envoltura normalmente es muy delgada, una envoltura de C++/CLI no necesita que conozca específicamente C++/CLI. Lo que necesita saber se puede encontrar en la especificación del lenguaje , es una extensa documentación con muchos ejemplos. P / Invoke es más bien una característica agradable de tener para bibliotecas existentes más pequeñas bien establecidas, pero si la interfaz para llamar a esa biblioteca cambia, se encontrará con un problema. Con C++ / CLI todavía puede tener una interfaz pública administrada en su proyecto de C++/CLI que está expuesta para el código administrado y manejar los cambios en la API de C de esa manera más fácilmente.

Si quieres deshacerte del DLL extra siempre puedes probar ILMerge, pero no estoy seguro de si es capaz de manejar ensamblajes mixtos, (aparentemente no), pero parece que es posibilidad de vincular tanto gestionado como no gestionado *.archivos obj con el enlazador de PlatformSDK como este:

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
 4
Author: John Leidegren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-01 16:47:19

C++/CLI será más fácil de depurar si tiene personal que sabe cómo depurar C++. Si no lo haces, podría ser mucho más difícil.

Sugeriría que la compensación aquí es entre la facilidad de uso para los consumidores de su conjunto interop versus la facilidad de mantenimiento para el propio conjunto. Si tiene un núcleo sólido de ingenieros sénior que están familiarizados con C++ y que pueden mantener el ensamblaje de manera confiable, será mucho más fácil para el resto de su equipo que no está familiarizado con código nativo para darles una interfaz totalmente administrada que se encarga de todo por ellos.

Por otro lado, si eres la única persona en la tienda con experiencia en C++, estaría muy recelosa de incrustar un módulo de C++ en el proyecto, en caso de que alguien más tenga que mantenerlo más tarde.

 2
Author: Dan Story,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-01 16:27:52

Para una API de este tamaño (~40 puntos de entrada totales), dibujaría la línea divisoria entre C++/CLI y P/Invoke en función de la cantidad de "mugre de archivo de encabezado" que tiene que duplicar en C#. Si es una cantidad pequeña (a modesta), P/Invoke está bien. Una vez que empiezas a duplicar un montón de .Archivos H en C#especially especialmente para cosas que no están expuestas en su API. NET might podría ser mejor usar C++ / CLI.

 2
Author: Ðаn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-01 17:09:28

Muchas respuestas buenas aquí - otra perspectiva es el plan para la API C existente. Los argumentos para usar PInvoke incluyen:

  • Necesita mantener una API de C para compatibilidad con otros consumidores C
  • Debe mantener el código en C como es grande y la migración también lo es caro

Los argumentos para usar C++/CLI incluyen:

  • desea mover la mayor cantidad de código posible al CLR

En este caso puede comenzar con C++ / CLI y luego muévase más y más a C#

 0
Author: Scott Weinstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-01 16:48:30