Tengo problemas de pérdida de memoria con un C++ dll de terceros. Para ciertas llamadas, el dll asigna memoria para la cadena, la pasa como un char * y luego espera recibir ese puntero para que pueda desasignar la memoria.Recibir un char * de C++ en C#, y pasarlo de nuevo
Aquí hay algunos comentarios del archivo de encabezado, un par de ejemplos de dónde se devuelve el carácter * y la firma del método "Versión".
(El dll se llama SW_API, es de una cámara de comercio - si alguien ya ha envuelto esto, ¡me encantaría hablar con ellos!).
/* Strings returned by the API are similarly normal nul-terminated C strings.
* The user should not attempt to change any of the bytes or read past the
* terminating nul of any returned string. All returned strings must be
* released using SW_ReleaseString() once the user is finished with the
* result. Failure to do this will result in memory leaks.
*/
/**
* @typedef const char* SW_XML
* @brief A string containing an XML documents text.
* @note As with all output strings, returned XML must be freed
* by the user. See @ref resource.
* @sa ErrorCodes
*/
typedef const char* SW_XML;
const char* STDAPICALLTYPE SW_GetLastErrorSpecifics();
SW_ErrCode STDAPICALLTYPE SW_DealGetSWML(SW_LoginID lh,
const char* swmlVersion,
SW_DealVersionHandle dealVersionHandle,
SW_XML* resultXML_out);
void STDAPICALLTYPE SW_ReleaseString(const char* buffer);
Intentar leer a partir de diversas fuentes, que han intentado el siguiente:
// Extern declarations
[DllImport(sw_api_dll, EntryPoint = "[email protected]", CharSet = CharSet.Ansi)]
public static extern IntPtr SW_GetLastErrorSpecifics();
[DllImport(sw_api_dll, EntryPoint = "[email protected]", CharSet = CharSet.Ansi)]
public static extern int SW_DealGetSWML(int lh, string swmlVersion, string dealVersionHandle, [Out] out IntPtr outputSWML);
[DllImport(sw_api_dll, EntryPoint = "[email protected]", CharSet=CharSet.Ansi)]
public static extern void SW_ReleaseString(IntPtr buffer);
// Using the externs.
private static string GetIntPtrStringAndRelease(IntPtr ptr)
{
string result = Marshal.PtrToStringAnsi(ptr);
API.SW_ReleaseString(ptr);
return result;
}
public static int SW_DealGetSWML(int lh, string swmlVersion, string dealVersionHandle, ref string outputSWML)
{
IntPtr outputSWML_out = new IntPtr();
int result = API.SW_DealGetSWML(lh, swmlVersion, dealVersionHandle, out outputSWML_out);
outputSWML = GetIntPtrStringAndRelease(outputSWML_out);
return result;
}
public static string SW_GetLastErrorSpecifics()
{
IntPtr ptr = API.SW_GetLastErrorSpecifics();
return GetIntPtrStringAndRelease(ptr);
}
Parece que no puedo conseguir la API para liberar las cuerdas.
Ahora, es posible que esto sea solo un error en la API, pero lo dudo. Es más probable que esté haciendo algo fundamentalmente erróneo.
Todo lo que sé es que mi conjunto de trabajo sigue creciendo.
La empresa en cuestión proporciona un contenedor Java pero no se extiende a un contenedor .Net.
Cualquier ayuda recibida con más gratitud.
Brett.
Esto parece un error en la API para mí. Si los datos que está obteniendo (es decir, el valor devuelto por 'GetIntPtrStringAndRelease' es bueno), entonces esto debería funcionar. –
'GetIntPtrStringAndRelease' se ve bien para mí. –
El valor que obtengo es bueno. ¡Casi me gustaría que no fuera así! – Brett