Estoy utilizando Pinvoke para la interoperabilidad entre el código nativo (C++) y el código administrado (C#). Lo que quiero lograr es obtener algo de texto del código nativo en mi código administrado. Para esto, intento muchas cosas, por ejemplo, pasar string/stringbuilder por ref, usar [IN] y [OUT], Marshaling to LPSTR, devolver string desde la función, etc. pero nada funciona en mi caso. Cualquier ayuda con algún código pequeño sería muy apreciada.Cómo devolver el texto del código nativo (C++)
Respuesta
que lo haría con un BSTR
ya que significa que usted no tiene que poner en nativa dos veces por cadena, una vez para obtener la longitud y luego una vez para obtener el contenido.
Con un BSTR
, el marshaller se encargará de desasignar el BSTR
con el administrador de memoria correcto para que pueda pasarlo con seguridad de su código C++.
C++
#include <comutil.h>
BSTR GetSomeText()
{
return ::SysAllocString(L"Greetings from the native world!");
}
C#
[DllImport(@"test.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string GetSomeText();
Hay un inconveniente menor de la BSTR
, a saber, que lleva una carga útil UTF-16, pero los datos de origen también puede ser char*
.
Para superar esto, puede terminar la conversión de char*
a BSTR
así:
BSTR ANSItoBSTR(const char* input)
{
BSTR result = NULL;
int lenA = lstrlenA(input);
int lenW = ::MultiByteToWideChar(CP_ACP, 0, input, lenA, NULL, 0);
if (lenW > 0)
{
result = ::SysAllocStringLen(0, lenW);
::MultiByteToWideChar(CP_ACP, 0, input, lenA, result, lenW);
}
return result;
}
Esa es la más difícil del camino, y ahora es fácil añadir otros envoltorios para convertir a BSTR
de LPWSTR
, std::string
, etc. std::wstring
Here es un tema sobre el que se discutió la clasificación de cadenas.
necesidad de para marcar el parámetro con el atributo
[MarshalAs(UnmanagedType.LPSTR)]
Aquí es un ejemplo de hacer esto a través de C#. Estoy llamando a la función nativa GetWindowText
a través de C# invocando. GetWindowText
devuelve el título de la ventana cuyo handle
se le pasa.
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
public static string GetText(IntPtr hWnd)
{
// Allocate correct string length first
int length = GetWindowTextLength(hWnd);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(hWnd, sb, sb.Capacity);
return sb.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
string str = GetText(this.Handle);
}
Si usted está volviendo un char *
, y no quiero tener que modificar el código C/C++ para asignar memoria para el valor de retorno (o no se puede modificar ese código), entonces puedes cambiar tu Prototipo de función Ctern extern para devolver un IntPtr
, y haz los cálculos tú mismo.
Por ejemplo, aquí es un fragmento de la interoperabilidad que escribí para Pocketsphinx:
[DllImport("sphinxbase.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr /* char const * */ jsgf_grammar_name(IntPtr /* jsgf_t * */ jsgf);
Y aquí está el acceso get para la clase C# JsgfGrammar
. m_pU
es un IntPtr
que apunta al objeto raw jsgf_t
.
public string Name
{
get
{
IntPtr pU = jsgf_grammar_name(m_pU);
if (pU == IntPtr.Zero)
strName = null;
else
strName = Marshal.PtrToStringAnsi(pU);
return strName;
}
}
Modificar este ejemplo para otros formatos de cadena (por ejemplo, Unicode) debe ser trivial.
- 1. genere y ejecute el código LLVM del nativo C/C++
- 2. inspeccionar el código nativo
- 3. ¿Qué es el código nativo?
- 4. Ejecución del código nativo por JVM/CLR
- 5. Código fuente del método nativo de Java
- 6. Ejecutando código nativo en Azure
- 7. Diferencia entre el código nativo y el código administrado?
- 8. pasando el valor del código nativo de iOS a cordova
- 9. Android: MediaRecorder @ Código nativo
- 10. ¿Cómo validar las credenciales de dominio (del código nativo)?
- 11. Cómo devolver el texto de respuesta AJAX?
- 12. cómo depurar código nativo puro en android?
- 13. Usando código C++ nativo en C# - problema con std :: vector
- 14. nativo C/C++ de código en una plataforma Android
- 15. El código C cambia el color del texto del terminal; cómo restaurar los valores predeterminados? Linux
- 16. Cómo compilar ocaml al código nativo
- 17. Propiedades similares a C# en C++ nativo?
- 18. ¿Cómo usar el código administrado del código no administrado?
- 19. Three.js portado al código nativo?
- 20. Cómo adjuntar el depurador para pasar al código nativo (C++) desde un contenedor administrado (C#)?
- 21. ver código nativo de Eclipse
- 22. Leer archivo de texto (Unicode) en 'C' usando Win32 nativo
- 23. ¿Obtiene Objective-C el código nativo o el código de bytes?
- 24. ¿Cómo devolver el valor del método parcial de C#?
- 25. ¿Es posible ejecutar código nativo de C++ en Windows Azure?
- 26. Convertir del puntero C++/CLI al puntero nativo de C++
- 27. ¿Cómo usar el código nativo de Android en phonegap?
- 28. Android: ¿Cómo transmitir intenciones desde el código nativo?
- 29. Windows Phone 7 el apoyo de código nativo
- 30. Cómo traducir código Byte a código nativo de la máquina
@rturrado Muchas gracias por sus correcciones en la edición. –
la respuesta es muy útil, por lo que se lo merece. Por cierto, me estoy dando cuenta de que 'bien puede chatear *' le falta un 'ser'. – rturrado
Puede pasar '-1' como cuarto argumento a' MultiByteToWideChar' para que la función calcule la longitud de la cadena automáticamente; evita la necesidad de llamar a 'lstrlenA' usted mismo. –