Parámetros por referencia de C# a C

21/12/2006 - 10:29 por moga | Informe spam
Hola,
Tengo una libreria en C que va a ser usada desde una plicación C#.

Esta librería en C tiene un método con parámetros pasados por
referéncia. Es decir, que la función actualizará los valores de esos
parámetros y esos cambios seran recogidos desde la aplicació en C#.

La librería C, (libreria.dll):
DllExport void pruebaChar(char **p_datos) {
strcpy(*p_datos, "hola");
}


Desde C# este método se usa así:

[DllImport(baseDir + "libreria.dll")]
unsafe private static extern void pruebaChar(char **p_datos);

public static string pruebaReferChar() {
unsafe {
char* pal = stackalloc char[10];

pruebaChar(&pal);
return new string(pal, 0, 10);
}
}

El caso es que, al llamar a pruebaChar(&pal) ocurre una excepción de
corrupción de memória, o bien devuelve datos inesperados.

Por favor, alguien podria orientarme sobre que hago mal?

Saludos,
Jose Luis

Preguntas similare

Leer las respuestas

#1 sharpman
21/12/2006 - 10:56 | Informe spam
Si estás usando VS2003, debes impedir que el CLR te cambie la dirección
física del puntero. Si la librería C la compilas con C++.Net, puedes hacer:

char __pin * dirFija = *p_datos;
strcpy(p_datos, "hola");

En otro caso puedes fijar el puntero desde C#:

fixed (char *pal = stackalloc char[10]) {
//... el codigo que llama a la funcion C
}

Si usas VS2005 tengo entendido que hay una notación mejorada
para distinguir entre punteros administrados y no administrados,
aunque aún no he necesitado probarla.
En este caso mira la documentación de C++/CLI

Saludos
Respuesta Responder a este mensaje
#2 sharpman
21/12/2006 - 11:04 | Informe spam
También ten en cuenta que te respondo sin probar lo que escribo,
y aquí hay una errata;

strcpy(p_datos, "hola") --> por strcpy(dirFija, "hola")

pero bueno, por ahí van los tiros ;-)
Respuesta Responder a este mensaje
#3 moga
21/12/2006 - 12:29 | Informe spam
Hola,
Gracias por responder tan rápidamente.

Estoy usando VS2005. La librería C está compilada en C, no en C++. Y
no puedo cambiarla porqué afecta a un montón de código que no
controlo.
Con C no puedo usar CLR.

La propuesta de incluir en fixed el stackalloc me da error. He mirado
en msdn y, por lo menos en 2005, no es necesario incluir stackalloc en
fixed.

¿Alguna otra idea?
Saludos,
Jose Luis


sharpman ha escrito:

También ten en cuenta que te respondo sin probar lo que escribo,
y aquí hay una errata;

strcpy(p_datos, "hola") --> por strcpy(dirFija, "hola")

pero bueno, por ahí van los tiros ;-)
Respuesta Responder a este mensaje
#4 sharpman
21/12/2006 - 12:59 | Informe spam
¿Alguna otra idea?



Bueno, parece que lo que haces en el código
es pasar la referencia donde se almacena un puntero
no administrado. El problema puede estar en que
la dirección de la referencia sí que cambia por culpa
del CLR, en ese caso puedes probar a fijar la referencia
de la siguiente manera:

public static string pruebaReferChar() {
unsafe {
char* pal = stackalloc char[10];
fixed (char **ppal = &pal) {
pruebaChar(ppal);
}
return new string(pal, 0, 10);
}
}

De esta manera la referencia a la variable pal, que probablemente
esté administrada, quedaría bloqueada para ser vista desde C.

Otra cosa no se me ocurre...
Respuesta Responder a este mensaje
#5 moga
21/12/2006 - 14:43 | Informe spam
Hola sharpman,

no. Tanto:
char* pal = stackalloc char[10];
fixed (char** ppal = &pal) {

como:
fixed (char *pal = stackalloc char[10]) {

dan el mismo error:
You cannot use the fixed statement to take the address of an already
fixed expression

Que biene a decir que la acción stackalloc ya fija la variable.

Llevo dos dias con este problema y estoy por pensar que la causa del
problema viene de C, no de C#.

Saludos,
Jose Luis


sharpman ha escrito:

>¿Alguna otra idea?

Bueno, parece que lo que haces en el código
es pasar la referencia donde se almacena un puntero
no administrado. El problema puede estar en que
la dirección de la referencia sí que cambia por culpa
del CLR, en ese caso puedes probar a fijar la referencia
de la siguiente manera:

public static string pruebaReferChar() {
unsafe {
char* pal = stackalloc char[10];
fixed (char **ppal = &pal) {
pruebaChar(ppal);
}
return new string(pal, 0, 10);
}
}

De esta manera la referencia a la variable pal, que probablemente
esté administrada, quedaría bloqueada para ser vista desde C.

Otra cosa no se me ocurre...
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida