CLR: .Net / Mono / Boo / Otros CLR > C#
Importar Dll
E.Baley:
A ver, por lo poco que sé, los problemas pueden estar en:
1) Ya lo habrás pensado, pero lo más obvio e inmediato es que, al hacer la llamada de la API desde tu programa, debes pasar el struct como referencia. Supongo que será un parámetro out, y que después de la llamada el struct habrá quedado modificado para que tu dispongas de los datos.
Por tanto, desdde C#, no sólo tienes que declarar la API con sus parámetros "ref", la llamada debe conterner también los "ref":
--- Código: Text ---// Al llamar al métodoGet_info(ref elFilename, ref laInfo);
2) El segundo problema que se me ocurre es al serializar el string para pasarlo dentro del struct. Concretamente "public string Serial_number;"
Peeero, los strings en C# son inmutables (si te fijas, cualquier operación sobre un string devuelve una copia del original modificado). Por tanto esa propiedad del struct no podrá ser modificada.
Prueba a pasar un buffer StringBuilder (de System.text) como Serial_number, sería algo así como:
--- Código: Text ---[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]struct INFO{ public PICTURE_TYPE Picture_type; public StringBuilder Serial_number; public byte Range; public ushort Code_page; public bool bRGB; public uint Buffer_16bpp_size;}
Como StringBuilder ya implementa ISerializable, no hace falta definir el "[MarshalAs( loquesea)]"
De momento no se me ocurre nada más ... si se me ocurre algo más ya lo pongo
RaYWoLF:
Gracias por la respuesta.
--- Código: Text --- Declaracion en el .h// return values:// 0 - ok// 1 - disk errorAPI int Get_info(char *File_name, //ININFO *Info //OUT); Declaracion en C#:[DllImport("midll.dll", EntryPoint = "Get_info")]private unsafe static extern int Get_info(string File_name, ref INFO Info); Ejecucion en C#:INFO info = new INFO();string fichero = "c:\\fichero.tif";int intResult = Get_info(fichero, ref info);
Sobre lo de pasarlos por referencia, como puedes ver el objeto INFO asi lo paso. El nombre del fichero no lo mando por referencia porque el propio string, hasta donde yo se, es equivalente a char * (de hecho con eso no hay problema porque el fichero si que lo encuentra correctamente).
Respecto a lo de utilizar el StringBuilder, efectivamente parece que seria la mejor opcion porque como tu comentas el string cada vez que lo modificas lo que hace es crear uno nuevo. Eso lo lei en este articulo (http :// msdn2.microsoft.com/es-es/magazine/cc301501(en-us).aspx), el problema es que al ejecutar el metodo Get_info me saca este error:
---------------
No se puede calcular la referencia del campo 'Serial_number' del tipo 'INFO': El campo de clase o el campo de estructura no puede ser del tipo StringBuilder. Normalmente se puede conseguir el mismo efecto utilizando un campo String y realizando una inicialización previa de éste en una cadena con una longitud que coincida con la longitud del búfer apropiado.
---------------
Aparte de eso, si lo declarase como StringBuilder sin mas (sin hacer el new porque dentro del struct no me deja), no podria especificarle un tamaño exacto, en este caso 8, no?. Otra cosa que probé fue a utilizar "fixed char Serial_number[8]" en lugar del string, pero tampoco parece que me devuelva resultados coherentes.
E.Baley:
Bueno, por lo menos ahora ya lo tengo más claro, el problema está identificado.
Necesitamos:
- Un struct pasado por referencia.
- El campo Serial_number del struct debe ser un string, ya inicializado, de 8 caracteres y modificable.
Podrías:
--- Código: Text ---// Declaración del Struct[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]struct INFO{ public PICTURE_TYPE Picture_type; public char[] Serial_number; public byte Range; public ushort Code_page; public bool bRGB; public uint Buffer_16bpp_size;}
--- Código: Text ---// Ejecucion en C#:string fichero = "c:\\fichero.tif"; INFO info = new INFO();info.Serial_number = new char[8]; // Aquí inicializamos ese campo int intResult = Get_info(fichero, ref info);
Como ya está identificado el problema, sólo queda averiguar cual es el tipo correcto que debes pasar, ya inicializado, al campo del Struct.
En el ejemplo anterior he pasado el "Serial_number" inicializado, pero dentro del Array de chars, cada posición no está inicializada todavía. (es decir, "Serial_number" está inicializado, pero Serial_number[1] no).
Si necesitas que también esto esté inicializado, puedes hacer:
--- Código: Text ---// Ejecucion en C#:string fichero = "c:\\fichero.tif"; INFO info = new INFO();string str_sernum = "12345678";char[] arr_sernum = pr.ToCharArray();info.Serial_number = arr_sernum; // Aquí inicializamos ese campo int intResult = Get_info(fichero, ref info);
Por lo demás, probar qué otros tipos se pueden pasar.
Por otra parte, el StringBuilder se puede también inicializaar de la misma forma.
--- Código: Text ---// Ejecucion en C#:string fichero = "c:\\fichero.tif"; INFO info = new INFO();StringBuilder SB_sernum = new StringBuilder(8); // inicializado y declarada su capacidadinfo.Serial_number = SB_sernum; // Aquí inicializamos ese campo int intResult = Get_info(fichero, ref info);
(El ejemplo era sólo para ver cómo se inicializa, porque el compilador nos ha dicho ya que un StringBuilder no va a servir. En cualquier caso, yo lo probaría porque no cuesta nada).
Suerte.
RaYWoLF:
Efectivamente, en c++ la funcion recibe un puntero a char (el nombre del fichero, que con un string parece que va bien) y un puntero a un objeto tipo INFO (el struct), por lo que necesitamos enviarlo por referencia ya que el metodo modifica el contenido de dicho struct.
Si utilizo char[] en lugar de string (tambien lo habia probado), aunque lo inicialice tal y como dices, me devuelve este error:
Excepcion tipo -> SafeArrayTypeMismatchException
"La matriz especificada no pertenece al tipo esperado."
Respecto a lo del StringBuilder, tambien probe a inicializarlo tal y como lo has hecho, pero como te comenté antes salta una excepcion.
Gracias por el tiempo que le estas dedicando, que aunque no hayamos conseguido demasiados avances por lo menos se intenta ;-)
RaYWoLF:
Al final he solucionado mi problema creandome una dll en c++/cli porque no veia fin a este problema.
Gracias por la ayuda E.Baley ;)
Navegación
[#] Página Siguiente
[*] Página Anterior
Ir a la versión completa