• Martes 20 de Octubre de 2020, 21:30

Autor Tema:  Puntero A Struct Desde C# A Dll C++  (Leído 3500 veces)

Neopro

  • Miembro MUY activo
  • ***
  • Mensajes: 316
    • Ver Perfil
Puntero A Struct Desde C# A Dll C++
« en: Jueves 3 de Mayo de 2007, 16:55 »
0
Holas Amigos, aun luchando con las DLL de C++ y sus tipos para utilizarlos en C#, ahora lo que me queda por realizar es lo siquiente:

En C++ (DLL)

Código: Text
  1. #define MAT_CHART_MAX    192
  2. typedef enum {
  3.     eMatCore_A   = 0,
  4.     eMatCore_B   = 1,
  5.     eMatCore_C   = 2,
  6.     eMatCore_D   = 3,
  7.     eMatCore_Max = 4
  8. } MatCoreIndex;
  9.  
  10. typedef struct {
  11.     MatMinu sminu;    
  12.     MatMinu fminu;    
  13. } MatPair;
  14.  
  15. typedef struct {
  16.     int x;
  17.     int y;
  18.     int d;
  19. } MatAffin;
  20.  
  21. typedef struct {
  22.     MatPair        mat_chartinfo_a[MAT_CHART_MAX];  
  23.     MatPair        mat_chartinfo_z[MAT_CHART_MAX];  
  24.     int            mat_similitude[MAT_CHART_MAX];  
  25.     MatAffin       mat_affinfactor;              
  26.     unsigned short mat_score;                    
  27.     short          mat_status;                
  28. } MatSubResult;
  29.  
  30. typedef struct {
  31.     MatSubResult mat_res[eMatCore_Max];
  32. } MatResult;
  33.  
  34. API_TYPE short MatMatch1to1(
  35.     unsigned char  *i_sbt,    
  36.     unsigned char  *i_fbt,    
  37.     const MatMode  i_mat_mode,
  38.     MatResult      *o_chart,  
  39.     unsigned short *o_score    
  40. );
  41.  

Y en C# lo que llevo:

Código: Text
  1. public struct MatMinu
  2.         {
  3.             public int MNO;
  4.             public int X;  
  5.             public int Y;  
  6.             public int D;  
  7.         }
  8.  
  9.         public struct MatPair
  10.         {
  11.             public MatMinu sminu;    
  12.             public MatMinu fminu;    
  13.         }
  14.  
  15.         public struct MatAffin
  16.         {
  17.             public int x;
  18.             public int y;
  19.             public int d;
  20.         }
  21.  
  22.         public enum MatCoreIndex
  23.         {
  24.             eMatCore_A = 0,
  25.             eMatCore_B = 1,
  26.             eMatCore_C = 2,
  27.             eMatCore_D = 3,
  28.             eMatCore_Max = 4
  29.         }
  30.  
  31.         public struct MatSubResult
  32.         {
  33.             public MatPair mat_chartinfo_a;  
  34.             public MatPair mat_chartinfo_z;
  35.             public int mat_similitude;    
  36.             public MatAffin mat_affinfactor;                
  37.             public short mat_score;                    
  38.             public short mat_status;                    
  39.         }
  40.         public struct MatResult
  41.         {
  42.             public MatSubResult mat_res;
  43.         }
  44.       
  45.  [DllImport("Match.dll", EntryPoint = "MatMatch1to1", SetLastError = true,
  46.                 CharSet = CharSet.Unicode, ExactSpelling = true,
  47.                CallingConvention = CallingConvention.StdCall)]
  48.         public static extern short MatMatch1to1(
  49.                char* i_sbt,      
  50.                char* i_fbt,    
  51.                MatMode i_mat_mode,  
  52.                out MatResult o_chart,    //MatResult*
  53.                ref short o_score    
  54.          );
  55.  

En el Form1 de C# :

Código: Text
  1.  const int MAT_CHART_MAX = 192;
  2.  
  3.         public MatPair[] mat_chartinfo_a;
  4.         public MatPair[] mat_chartinfo_z;
  5.         public int[] mat_similitude;
  6.         public MatSubResult[] mat_res;
  7.         public MatResult mat_result;
  8.  

Y cuando llamo a la funcion(hay otras cosas en esta funcion que omití porq funcionan bien):

Código: Text
  1. mat_st = MatMatch1to1((char*)min1, (char*)min2, mat_mode, out mat_result, ref mat_score);
  2.  

Ahora Mi Duda: Esto me compila, pero la DLL no me retorna los valores que debiera en mat_result.

Algo estaré haciendo mal?, o hay algo que se me olvido hacer o no está bien como lo estoy haciendo?...

Muchisimas gracias.
              [size=109]"Has lo que digo y no hagas lo que hago"[/size]

Neopro

  • Miembro MUY activo
  • ***
  • Mensajes: 316
    • Ver Perfil
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #1 en: Viernes 4 de Mayo de 2007, 23:15 »
0
Y otra duda :

Como se crea esto en C#?

Código: Text
  1. typedef struct {
  2.    MatPair        mat_chartinfo_a[MAT_CHART_MAX];  
  3.    MatPair        mat_chartinfo_z[MAT_CHART_MAX];  
  4.    int            mat_similitude[MAT_CHART_MAX];  
  5.    MatAffin       mat_affinfactor;              
  6.    unsigned short mat_score;                    
  7.    short          mat_status;                
  8. } MatSubResult;
  9.  

Teniendo en cuenta:

Código: Text
  1.  
  2. int MAT_CHART_MAX = 192;
  3.  
  4.  
              [size=109]"Has lo que digo y no hagas lo que hago"[/size]

JuanK

  • Miembro de ORO
  • ******
  • Mensajes: 5393
  • Nacionalidad: co
    • Ver Perfil
    • http://juank.io
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #2 en: Sábado 5 de Mayo de 2007, 02:41 »
0
Cita de: "Neopro"
Y otra duda :

Como se crea esto en C#?

Código: Text
  1. typedef struct {
  2.    MatPair        mat_chartinfo_a[MAT_CHART_MAX];  
  3.    MatPair        mat_chartinfo_z[MAT_CHART_MAX];  
  4.    int            mat_similitude[MAT_CHART_MAX];  
  5.    MatAffin       mat_affinfactor;              
  6.    unsigned short mat_score;                    
  7.    short          mat_status;                
  8. } MatSubResult;
  9.  

Teniendo en cuenta:

Código: Text
  1.  
  2. int MAT_CHART_MAX = 192;
  3.  
  4.  
Código: Text
  1. public int const MAT_CHART_MAX = 192;
  2.  
  3. public struct MatSubR
  4. {
  5.    MatPair        mat_chartinfo_a[MAT_CHART_MAX];  
  6.    MatPair        mat_chartinfo_z[MAT_CHART_MAX];  
  7.    int            mat_similitude[MAT_CHART_MAX];  
  8.    MatAffin       mat_affinfactor;              
  9.    ushort mat_score;                    
  10.    short          mat_status;                
  11. }
  12.  
[size=109]Juan Carlos Ruiz Pacheco
[/size]
Microsoft Technical Evangelist
@JuanKRuiz
http://juank.io

Neopro

  • Miembro MUY activo
  • ***
  • Mensajes: 316
    • Ver Perfil
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #3 en: Sábado 5 de Mayo de 2007, 17:42 »
0
Eso me envia un error, ya que me dice que solo puede declarar Variables de los tipos conocidos, o sea:

byte, short, int, char, long... etc...

y no de Struct...

Y estoy usando Visual Studio 2005 con Framework 2.0, que dice que desde esta version se permite declarar tamaños en Struct.
              [size=109]"Has lo que digo y no hagas lo que hago"[/size]

JuanK

  • Miembro de ORO
  • ******
  • Mensajes: 5393
  • Nacionalidad: co
    • Ver Perfil
    • http://juank.io
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #4 en: Sábado 5 de Mayo de 2007, 22:32 »
0
Cita de: "JuanK"
Código: Text
  1. public int const MAT_CHART_MAX = 192;
  2.  
  3. public struct MatSubR
  4. {
  5.    MatPair        mat_chartinfo_a[MAT_CHART_MAX];  
  6.    MatPair        mat_chartinfo_z[MAT_CHART_MAX];  
  7.    int            mat_similitude[MAT_CHART_MAX];  
  8.    MatAffin       mat_affinfactor;              
  9.    ushort mat_score;                    
  10.    short          mat_status;                
  11. }
  12.  
oops claro!

Debiste notarlo ya a estas alturas...
por demas recuerda que ya casi no tengo tiempo y te conteste lo mas rapido que pude, esos errores deberías haberlos resuelto tu...

Lo que pasa es que desde luego en C# asi no se inicializan los arrays, por otro lado al tener que inicializarlos ya no te sirve una estructura con el constructor por defecto (segun recuerdo, pero prueba) asi que por eso lo converti en clase, lo cual de todas formas es mejor puesto que en C++ las clases y las estructuras funcionan de la misma manera ( en C# no es asi.)

Otro error que deberias haber tenido en cuenta es que sino declaras el tipo de acceso al objeto este se vuelve por defecto private, asi que si los dejas sin modificador e acceso el compilador te dirá que no conoce los miembros de la estructura, por eso debes dejarlos public.

<!--xc1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td>XCODE </td></tr><tr><td id='XCODE'><!--exc1-->
public class MatSubR
{
   public int const MAT_CHART_MAX = 192;
   public MatPair[]       mat_chartinfo_a =new MatPair[MAT_CHART_MAX];  
   public MatPair[]        mat_chartinfo_z=new MatPair[MAT_CHART_MAX];  
   public int[]            mat_similitude = new int[MAT_CHART_MAX];  
   public MatAffin       mat_affinfactor;              
   public ushort mat_score;                    
   public short          mat_status;                
} <!--xc2--></td></tr></table><div class='postcolor'><!--exc2-->
[size=109]Juan Carlos Ruiz Pacheco
[/size]
Microsoft Technical Evangelist
@JuanKRuiz
http://juank.io

Neopro

  • Miembro MUY activo
  • ***
  • Mensajes: 316
    • Ver Perfil
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #5 en: Domingo 6 de Mayo de 2007, 03:28 »
0
Ahhhh, OK.

Eso de las Clases y Struct en C# sabía que eran distintas, pero no sabia si eran o no compatibles con C++, ya probé todas las acciones posibles con struct, asi que por eso debi crear esta discución y por eso mismo te envie un correo, espero que no te haya molestado.

Entonces para los otros tipos derivados, tambien los podré declarar como clases?...

Y siempre los declaro como public, ya me habia topado con eso antes, tambien con las variables internas.

Oye y MUCHISIMAS GRACIAS por tu tiempo, si ya me habias dicho que estabas ocupado.

Atte.
              [size=109]"Has lo que digo y no hagas lo que hago"[/size]

JuanK

  • Miembro de ORO
  • ******
  • Mensajes: 5393
  • Nacionalidad: co
    • Ver Perfil
    • http://juank.io
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #6 en: Domingo 6 de Mayo de 2007, 17:22 »
0
En C++ una clase es un puntero en el stack apuntando a un bloque de memoria en el heap, en cambio una estructura también.

En C# una clase es un puntero en el stack apuntando a un bloque de memoria en el heap, en cambio una estructura es un bloque de memoria directamente alojado en el stack.

Por esta razón si en C++ te piden una estructura teóricamente le puedes enviar una clase ya que es el mismo de tipo de construcción.
[size=109]Juan Carlos Ruiz Pacheco
[/size]
Microsoft Technical Evangelist
@JuanKRuiz
http://juank.io

Neopro

  • Miembro MUY activo
  • ***
  • Mensajes: 316
    • Ver Perfil
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #7 en: Lunes 7 de Mayo de 2007, 18:28 »
0
Lo de las clases me permitio perfectamente incializar los valores necesarios para las funciones que necesito, el problema que me surgio es que debo declara otro struct como clase para poder hacer todo bien, pero no me permite el acceso a los campos, a que me refiero, que creo otra clase con los nombres a los cuales quiero acceder, pero al compilar y ver los valores que me arroja la variable, simplemente los guarda como null y no asigna lo que está en la otra clase, es decir no se puede acceder.

Que hago?, necesito inicializar los tamaños, pero no como class no puedo acceder desde otra, pero si como struct.
              [size=109]"Has lo que digo y no hagas lo que hago"[/size]

JuanK

  • Miembro de ORO
  • ******
  • Mensajes: 5393
  • Nacionalidad: co
    • Ver Perfil
    • http://juank.io
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #8 en: Lunes 7 de Mayo de 2007, 18:31 »
0
no entiendo muy bien lo que dices, pero si en definitiva necesitas que sean struct
entonces crealo como struict
pero cada uno de los miembros del struct
debes inicializarlo posterior a la creacion de la instancia
ya que dentro del propio struct no te lo permitira.
[size=109]Juan Carlos Ruiz Pacheco
[/size]
Microsoft Technical Evangelist
@JuanKRuiz
http://juank.io

Neopro

  • Miembro MUY activo
  • ***
  • Mensajes: 316
    • Ver Perfil
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #9 en: Lunes 7 de Mayo de 2007, 18:40 »
0
Es que dentro del struct solo puedo declararlo como variables sin tamaño fijo. Y al declararlas afuera no me permite cambiar a variables de tamaño fijo.

O sea sigue siendo una variable unidimensional.

Código: Text
  1. //ESTO NO ES VALIDO
  2. public struct MatMinu
  3.        {
  4.            public int MNO;
  5.            public int X;  
  6.            public int Y;  
  7.            public int D;  
  8.        }
  9.  
  10.        public struct MatPair
  11.        {
  12.            public MatMinu sminu;    
  13.            public MatMinu fminu;    
  14.        }
  15.  
  16.        public struct MatAffin
  17.        {
  18.            public int x;
  19.            public int y;
  20.            public int d;
  21.        }
  22.  
  23.        public enum MatCoreIndex
  24.        {
  25.            eMatCore_A = 0,
  26.            eMatCore_B = 1,
  27.            eMatCore_C = 2,
  28.            eMatCore_D = 3,
  29.            eMatCore_Max = 4
  30.        }
  31.  
  32.        public struct MatSubResult
  33.        {
  34.            //ESTO NO ES VALIDO, SOLO ES LO QUE DESEO HACER
  35.            public MatPair[] mat_chartinfo_a = new MatPair[MAT_CHART_MAX ];  
  36.            //ESTO NO ES VALIDO, SOLO ES LO QUE DESEO HACER
  37.            public MatPair[] mat_chartinfo_z = new MatPair[MAT_CHART_MAX ];
  38.            //ESTO NO ES VALIDO, SOLO ES LO QUE DESEO HACER
  39.            public int[] mat_similitude = new MatPair [MAT_CHART_MAX];    
  40.            public MatAffin mat_affinfactor;                
  41.            public short mat_score;                    
  42.            public short mat_status;                    
  43.        }
  44.        public struct MatResult
  45.        {
  46.            //ESTO NO ES VALIDO, SOLO ES LO QUE DESEO HACER
  47.            public MatSubResult[] mat_res = new MatSubResult[(int)MatCoreIndex.eMatCore_Max];
  48.        }
  49.  

Asi deberia ser, pero no me lo permite, y cuando las inicializo afuera como arreglos con ese tamaño, tampoco les cambia el tamaño.

Pero la principal funciono muy bien con class de la siguiente forma:

Código: Text
  1. public class MatResult
  2.        {
  3.            public MatSubResult[] mat_res = new MatSubResult[(int)MatCoreIndex.eMatCore_Max];
  4.        }
  5.  

Pero eso no me permite acceder mas alla de MatSubResult.
              [size=109]"Has lo que digo y no hagas lo que hago"[/size]

Neopro

  • Miembro MUY activo
  • ***
  • Mensajes: 316
    • Ver Perfil
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #10 en: Lunes 7 de Mayo de 2007, 23:01 »
0
Creo que ya he intentado muchas formas de hacerlo y no puedo creer que me acerco a la opcion de que no podré hacer lo que deseo.

Los struct no me permiten deifnir arreglos y si los declaro e inicializo fuera, no toma los tamaños especificados.

La clase no me permite que sea llamada como puntero y ademas si defino tipos, no me permite, ver mas alla del segundo tipo:

Código: Text
  1. public class prueba
  2. {
  3. public tipo1[] var1 = new tipo1[4];
  4. public tipo2 var2;
  5. }
  6.  
  7. public struct tipo1
  8. {
  9. public tipo4[] var4; //Acá no puedo declarar tamaño y si lo hago afuera,
  10. // tampoco lo acepta, o sea compila, pero no ejecuta la accion de asignar memoria
  11. }
  12.  
  13. public struct tipo2
  14. {
  15. public int algo;
  16. }
  17.  
  18. public struct tipo 4
  19. {
  20. public char otro;//No se ve desde la clase, con struct si, pero
  21. //necesito el struct con tamaño definido
  22. }
  23.  

En ese ejemplo, no puedo tener acceso al tipo 4 desde la clase.

Lo ideal sería con struct, pero con el primero en clase, es lo que mas se acerca a lo que necesito.
              [size=109]"Has lo que digo y no hagas lo que hago"[/size]

JuanK

  • Miembro de ORO
  • ******
  • Mensajes: 5393
  • Nacionalidad: co
    • Ver Perfil
    • http://juank.io
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #11 en: Martes 8 de Mayo de 2007, 14:48 »
0
Cita de: "JuanK"
debes inicializarlo posterior a la creacion de la instancia
ya que dentro del propio struct no te lo permitira.
Código: Text
  1.        public struct MatSubResult
  2.       {
  3.           public MatPair[] mat_chartinfo_a;  
  4.           public MatPair[] mat_chartinfo_z;
  5.           public int[] mat_similitude;    
  6.           public MatAffin mat_affinfactor;                
  7.           public short mat_score;                    
  8.           public short mat_status;                    
  9.       }
  10. ...
  11. ...
  12. ...
  13.       public void Inicializar()
  14.       {
  15.  
  16.          MatSubResult[] m = new MatSubResult[(int)MatCoreIndex.eMatCore_Max];
  17.  
  18.           for(int i=0; i &#60; (int)MatCoreIndex.eMatCore_Max; i++)
  19.           {
  20.                m[i].mat_chartinfo_a = new MatPair[MAT_CHART_MAX ];  
  21.                m[i].mat_chartinfo_z = new MatPair[MAT_CHART_MAX ];
  22.                m[i].mat_similitude = new MatPair [MAT_CHART_MAX];    
  23.           }
  24.       }
  25. ...
  26. ...
  27. ...
  28.  
[size=109]Juan Carlos Ruiz Pacheco
[/size]
Microsoft Technical Evangelist
@JuanKRuiz
http://juank.io

Neopro

  • Miembro MUY activo
  • ***
  • Mensajes: 316
    • Ver Perfil
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #12 en: Martes 8 de Mayo de 2007, 15:47 »
0
Oh, genial, esa es la estructura que necesito, pero tengo un solo problema:

MatResult mat_result = new MatResult();

Queda asignada como null... ...o sea se crea todo, menos la variable raiz, ya que es esa variable a la que tengo que obtener el puntero y poder enviarla a la DLL.

Muchas gracias...

Creo que resolví el tema, espero que me funcione bien, ahora estoy haciendo pruebas...
              [size=109]"Has lo que digo y no hagas lo que hago"[/size]

Neopro

  • Miembro MUY activo
  • ***
  • Mensajes: 316
    • Ver Perfil
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #13 en: Martes 8 de Mayo de 2007, 17:04 »
0
Mmm, ya una vez estando las estructuras listas me envia el siguiente error:

El parámetro no es correcto. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))

En algunos foros, dice que hay que reinstalar el Framework, pero no creo que sea eso, aunque lo hice, y continua el mismo error.

En otros dicen que pueden ser problemas con la version de la DLL, pero yo la llamo antes con otra funcion y no arroja problemas.

Creo que tengo problemas al hacer un ref u out a mat_result, ya que no me permite pasarlo como puntero.

ERROR: Error No se puede adquirir la dirección, obtener el tamaño ni declarar un puntero a un tipo administrado.
              [size=109]"Has lo que digo y no hagas lo que hago"[/size]

Neopro

  • Miembro MUY activo
  • ***
  • Mensajes: 316
    • Ver Perfil
Re: Puntero A Struct Desde C# A Dll C++
« Respuesta #14 en: Miércoles 9 de Mayo de 2007, 21:29 »
0
Y al final se pueden crear punteros a tipos administrados???? o struct administrados????
              [size=109]"Has lo que digo y no hagas lo que hago"[/size]