2010-08-26 17 views
5

Mi pregunta está estrechamente relacionada con la forma en que una DLL exporta clases C++ y métodos genéricos (wrt características de lenguaje C++ sin un C# paralelo).¿Cómo uso una biblioteca C++ de C# y .NET?

Creo que puede llamar a las funciones dentro de un bloque extern "C" desde C# simplemente haciendo referencia a la DLL y usando DLLImport. ¿Pero puede crear una instancia de un tipo de C++ con plantillas? ¿Qué ocurre si el tipo de C++ tiene somethin' crazy que no es compatible con C#? ¿Existe un RFC o una parte relevante de C# specification?

Gracias ...

EDIT: Ahora me encontré con P/Invoke que debe ser valioso, pero todavía estoy en busca de una especificación o norma con respecto a este.

Respuesta

7

La manera correcta de hacerlo es utilizar C++ administrado para acceder a C++ no administrado y compilarlo en un ensamblado.

+0

¿Más información sobre esto? Soy nuevo en la programación de Windows, estoy acostumbrado a Unix, enlaces estáticos y Makefiles ... ¿Cómo creo una DLL administrada o una DLL no administrada con C++ en VS2010? –

+0

@robert http://ondotnet.com/pub/a/dotnet/2004/03/29/mcpp_part3.html – 0x4f3759df

+0

@robert El enlace de arriba expone la muy antigua sintaxis de C++ administrada y obsoleta, '__gc' se convierte en' ref' en sintaxis moderna, por ejemplo. – jdehaan

2

Creo que se puede llamar a funciones dentro de un bloque extern "C" de C# por acaba de hacer referencia a la DLL.

incorrecto, usted tiene que utilizar DllImport o los llamados PInvoke (invocación de plataforma) para llamar a una función nativa C desde código administrado. La referencia funciona solo para ensamblados .NET o COM con un automatically generated interop dll.

El uso de C++ desde C# se convierte en una verdadera pesadilla debido a la manipulación de nombres entre otras cosas.

Si puede, puede compilar un C++ Dll administrado como un contenedor para hacer que ambos mundos se encuentren. Esto también tiene la ventaja de que puede marcar su conjunto como ComVisible, por lo que está disponible para muchas herramientas capaces de manejar COM.

Una alternativa es escribir un envoltorio de C alrededor de la API de C++, lo que puede ser tedioso y feo.

EDIT:

Ayuda para decidir qué método utilizar:

  • 1) Usted tiene un archivo DLL nativo de C
    • ADVERTENCIA: si utiliza un .lib de C++ administrada, a continuación, el dll no está realmente vinculado dinámicamente y no puede reemplazarse con una simple inserción de una versión compatible más nueva.
    • preferida: Uso P/Invoke desde cualquier lenguaje .NET (gota en el reemplazo posible)

  • 2) Usted tiene un nativo de C++ DLL
    • NO use P/Invoke, esta es una verdadera pesadilla (debido a que el nombre se altera entre otras cosas)
    • PREFERIDO: Compilar un contenedor .NET dll con C++ administrado, funciona solo si tiene un compilador compatible con el que se usó para compilar el dll nativo.
    • Si la DLL nativa se compiló con un compilador incompatible (Compilador A) del que puede usar para C++ administrado (Compilador C), entonces recomiendo construir (con el mismo compilador A) un envoltorio de C alrededor del C++ nativo dll. A continuación, utilice el método P/Invoke para utilizar este envoltorio C DLL como se describe en 1)
+0

gracias por la corrección. ¿Puedes crear un ensamblado .NET con C++? –

+0

Sí, pero con Managed C++ que en realidad no es C++, pero te permitirá enlazar con C++ Dlls nativos si utilizas el mismo compilador que los tipos que generaron el dll puro de C++ que estás utilizando. – jdehaan

+0

P/Invoke no es divertido – 0x4f3759df

1

Lo que hace el DLL internamente es irrelevante, por lo que C# se refiere. Tenga en cuenta que las plantillas de C++ no generan ningún código hasta que se crea una instancia de la plantilla. Si la plantilla simplemente se define en algún lugar de los archivos de encabezado DLL, entonces no habrá ningún código generado para esa plantilla en la DLL. Por otro lado, si el DLL explícitamente instancia y exporta algunos tipos de plantillas, entonces teóricamente podrías llamarlos desde C#.

Hay dos problemas que debe superar. La primera es que los compiladores de C++ destruyen sus nombres de método, por lo que tendrías que averiguar exactamente cuál es el nombre correcto para PInvoke. El segundo problema es que no hay forma de crear objetos CRT en C# directamente. Tendría que definir algunos métodos de fábrica y exportarlos también.

Francamente, creo que esto es mucho más problemático de lo que vale. Sería mejor crear una API de estilo C para la DLL y llamar a esas funciones desde C#. Internamente, las funciones podrían crear y manipular los objetos relevantes de C++.

+0

Bien, suena como un dolor gigante. Crear una API C es una solución justa, pero estoy sorprendido de que no haya un mecanismo de interoperabilidad más flexible ... –

+1

El mecanismo de interoperabilidad debería manejar todos los esquemas de manipulación posibles para cualquier compilador ya que no hay un estándar para esto (eso es un gran dolor) y clasificación/desemparejamiento no es trivial. En el caso de COM, todo se especifica en interfaces y los tipos están bien definidos en términos de tamaño y alineación. – jdehaan

Cuestiones relacionadas