2009-04-28 16 views
9

En una función en mi DLL C++, devuelvo una cadena std :: a mi aplicación C#. Es más o menos el siguiente aspecto:Devolviendo una cadena std :: desde una DLL C++ a un programa C# -> Dirección no válida especificada a RtlFreeHeap

std::string g_DllName = "MyDLL"; 

extern "C" THUNDER_API const char* __stdcall GetDLLName() 
{ 
    return g_DllName.c_str(); 
} 

Pero cuando mi C# código llama a esta función, me sale este mensaje en mi ventana de salida:

Invalid Address specified to RtlFreeHeap(00150000, 0012D8D8) 

La declaración de la función en C# es el siguiente:

[DllImport("MyDll", EntryPoint = "GetDLLName")] 
    [return: MarshalAs(UnmanagedType.LPStr)] 
    public static extern string GetDLLName(); 

De lo que he podido encontrar en línea, a veces este mensaje aparece cuando hay una inconsistencia entre qué versión de nuevo (depuración o versión, etc.) se está utilizando con eliminar. Pero no estoy seguro si eso es lo que está pasando en mi caso. Así que no estoy seguro de qué es lo que lo está causando. Tal vez los MashallAs podrían tener algo que ver con eso?

¿Alguna idea?

Gracias!

+0

Se puede comprobar lo que ha encontrado es decir, a) si está utilizando las bibliotecas correctas (depuración) para versiones de depuración, etc y b), este problema se produce tanto en la depuración y lanzar versiones yc) intentar usar/clr: pure en lugar de/clr para su dll de C++. – dirkgently

Respuesta

12

He logrado encontrar el problema. Fue la forma en que se realizó la definición de C#. Por lo que puedo entender, el uso de MarshallAs (UnmanagedType.LPStr) en combinación con el tipo de retorno de cadena hace que intente liberar la cadena cuando termina. Pero debido a que la cadena proviene de la DLL C++, y muy probablemente un administrador de memoria totalmente diferente, falla. E incluso si no falló, no quiero que se libere de todos modos.

La solución que encontré fue a cambiar la declaración de C# para esto (el código C++ es sin cambios):

[DllImport("MyDll", EntryPoint = "GetDLLName")] 
public static extern IntPtr GetDLLName(); 

Así que esto hace que sea para que sólo devuelve un puntero a los datos de cadena. Y luego cambiar a una cadena, pasarlo a Marshal.PtrToStringAnsi()

return Marshal.PtrToStringAnsi(GetDLLName()); 

y que se envuelve en otra función para la limpieza.

he encontrado la solución de esta página: http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=1108

Cuestiones relacionadas