2011-03-20 8 views
6

Quiero hacer un C++ nativo, todo lo que se puede usar desde un proyecto de C#.C# llamando a C++ nativo todas las funciones: ¿qué tipos usar?

  • Si quiero pasar una cadena de C# a la función en C++, ¿qué parámetro debo usar?
  • Sé que las cadenas C# usan Unicode, así que probé wchar_t * para la función pero no funcionó; Intenté capturar cualquier excepción planteada desde la función llamada, pero no se lanzó ninguna excepción.
  • También quiero devolver una cadena para que pueda probarla.

La función de C++ es el siguiente:

DECLDIR wchar_t * setText(wchar_t * allText) { 
    return allText; 
} 

El código C# es la siguiente:

[DllImport("firstDLL.Dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]  
public static extern string setText(string allText); 

var allText= new string('c',4); 
try { 
    var str1 = setText(allText); 
} 
catch (Exception ex) { 
    var str2 = ex.Message; 
} 

¿Qué tipo debo usar para el tipo de retorno de C++ de función, de modo que pueda llamarlo desde C# con un tipo de devolución de string[]? la misma Q pero para que el parámetro de la función sea string [] en C#?

+1

Por cierto, el uso de var como este pronto regresará para morderte cuando descubras que no tienes idea de qué tipo son tus variables. –

+0

Tan pronto como compile estas 3 var (s) se convierten en una cadena. – ukhardy

+2

@ukhardy oh vamos, lo sé! El punto es que cuando tienes var diseminado por todo tu código, y es más complejo que esto, encuentras que se convierte en un obstáculo para entender el código existente. –

Respuesta

3

Probablemente lo haga con un COM BSTR y evite tener que meterse con la asignación de búfer. Algo como esto:

C++

#include <comutil.h> 
DECLDIR BSTR * setText(wchar_t * allText) 
{ 
    return ::SysAllocString(allText); 
} 

C#

[DllImport(@"firstDLL.dll", CallingConvention = CallingConvention.Cdecl)] 
[return: MarshalAs(UnmanagedType.BStr)] 
private static extern string setText(string allText); 

BSTR es el tipo de cadena COM nativo. La ventaja de usarlo aquí es que la memoria puede asignarse en el lado nativo de la interfaz (en C++) con el asignador COM, y luego destruirse en el lado administrado de la interfaz con el mismo asignador. El Marshaller P/Invoke sabe todo sobre BSTR y maneja todo por usted.

Si bien puede resolver este problema pasando las longitudes de búfer, resulta en un código bastante desordenado, por lo que tengo una preferencia por BSTR.


a su segunda pregunta, acerca de P/Al invocar string[], yo creo que encontrará lo que necesita de Chris Taylor's answer a otra pregunta aquí en desbordamiento de pila.

+0

Realmente necesito poder tener cualquier char de esa palabra de Microsoft puede usar para que la Q sea: ¿BSTR puede mantener unicode char? – ghet

+0

@ghet ¡BSTR solo tiene carácter Unicode! Es perfecto para tus necesidades en mi opinión. –

+0

en cuanto a la segunda Q: qué usar en C++ para el tipo de devolución para que pueda tener una cadena [] tipo de devolución en C#, ¿me puede ayudar con eso? – ghet

0

C++

void GetString(char* buffer, int* bufferSize); 

C#

int bufferSize = 512; 
StringBuilder buffer = new StringBuilder(bufferSize); 
GetString(buffer, ref bufferSize) 
+1

Esta es una respuesta parcial que no ayuda mucho sin implementaciones. –

+0

P/Invoke marshaller tiene soporte explícito para cadenas terminadas en cero. Implementaciones? – ukhardy

+0

¡eso es cierto, pero el problema es que los contenidos provienen de un asignador de memoria externo! –

Cuestiones relacionadas