He leído otras preguntas similares sobre esto, pero no resuelven este problema en particular. Tengo una antigua biblioteca C con una función touppercase (como ejemplo). Esto toma un char * y devuelve un char *. Sin embargo, el puntero devuelto es un puntero a la misma cadena (no me preguntes si no lo escribí).Llamar a una función C DLL Con char * Parámetros con P/Invoke
La función tiene el siguiente aspecto:
__declspec(dllexport)
char * __cdecl touppercase(char *ps_source)
{
char *ps_buffer = NULL;
assert (ps_source != NULL);
ps_buffer = ps_source;
while (*ps_buffer != '\0')
{
*ps_buffer = toupper(*ps_buffer);
ps_buffer++;
}
*ps_buffer = '\0';
return (ps_source);
}
El código C# para declarar esto se parece a:
[DllImport("mydll.dll", EntryPoint = "touppercase",
CharSet = CharSet.Ansi, ExactSpelling = true,
CallingConvention = CallingConvention.Cdecl)]
private static extern System.IntPtr touppercase(string postData);
La llamada a este en mi aplicación parece
string sTest2 = Marshal.PtrToStringAnsi(to_uppercase(sTest));
Sin embargo sTest2 acaba siendo una cadena aleatoria.
Agregué una función de prueba al mismo dll con los mismos parámetros pero esto asigna memoria localmente y copia la cadena. Esto funciona bien ¿Por qué la versión original ahora funciona?
Nota: La actualización de las bibliotecas dll no es una opción.
¿Qué sucede con sTest después de una llamada a esta función? ¿cambia? –
¿Por qué declaras la convención de llamadas? Por defecto, C# usa la convención de llamadas en lugar de la convención estándar (C/C++). Ya cambias la convención en tu biblioteca C. Solo tendrías que cambiar la convención si el código C no fue declarado como algo diferente al predeterminado. –
@ramhound: la especificación explícita de la convención de llamadas de las funciones exportadas es más segura. No desea que las exportaciones se vean afectadas por '/ Gr' o'/Gz'. –