Pregunta

Tengo una función en C# que pasa una serie de estructuras a una DLL escrita en C++.La estructura es un grupo de entradas y cuando leo los datos en la DLL, todos los valores salen bien.Sin embargo, si intento escribir en los elementos desde C++, los valores nunca aparecen cuando intento leerlos y luego volver a C#.

C#

[StructLayout(LayoutKind.Sequential)]
struct Box
{
  public int x;
  public int y;
  public int width;
  public int height;
}

[StructLayout(LayoutKind.Sequential)]
struct Spot
{
  public int x;
  public int y;
}

static void TestCvStructs()
{
  int len = 100;
  Box[] r = new Box[len];
  Spot[] p = new Spot[len];

  for (int i = 0; i < len; i++)
  {
    r[i].x = i*10;
    r[i].y = i * 200;
    r[i].width = r[i].x * 10;
    r[i].height = r[i].y * 100 + r[i].x * 5;

    p[i].x = i * 8;
    p[i].y = i * 12;
  }

  PassCvStructs(len, r, p);

  for (int i = 0; i < len; i++)
  {
    Console.WriteLine("Point/x:{0} Boxes/x{1}", p[i].x, r[i].x );
  }
}

[DllImport(dll)]
private static extern int PassSomeStructs(int count, Box[] boxes, Spot[] points);

C++

typedef struct Box
{
  int x;
  int y;
  int width;
  int height;
} Box;

typedef struct Spot
{
  int x;
  int y;
} Spot;

CPPDLL_API int PassSomeStructs(int arrayLength, Box *boxes, Spot *points)
{
  for(int i = 0; i < arrayLength; ++i)
  {
    printf("Group:%i\n", i);
    printf("Rect - x:%i y:%i width:%i length:%i\n", boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height);
    printf("Point - x:%i y:%i\n", points[i].x, points[i].y);
    printf("\n");

    points[i].x = 3;
    boxes[i].x = 1;
  }
  return 0;
}
¿Fue útil?

Solución 3

Encontré la respuesta publicada en otra pregunta: ¿Cómo Marshall matriz de estructuras en C#?

Al mariscal aparentemente, el valor predeterminado es reunir los parámetros como en. De lo contrario, deben ser declarados explícitamente como out o adentro. Después de especificar eso explícitamente, mi código ahora funciona.

Gracias a su Fragmentación para la respuesta y para Antonmarkov para la exposición a los mariscales.

private static extern int PassSomeStructs(int count, [In, Out] Box[] boxes, [In, Out] Spot[] points);

Otros consejos

Desde un Artículo de MDSN En matrices de mariscal: intente configurar el siguiente atributo en sus tipos de matriz. Esto normalmente se usa para llamar a C# de C ++, pero también puede ser necesario para obtener los valores actualizados nuevamente en C#.

[DllImport(dll)]
private static extern int PassSomeStructs(int count, 
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Box[] boxes, 
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Spot[] points);

También vea este artículo para obtener un ejemplo de exitoso mariscal de dos vías:

http://social.msdn.microsoft.com/forums/en-us/csharplanguage/thread/ff0123d0-506b-4de2-bfb5-f690c9358826/

¿Ha intentado agregar la palabra clave Ref/Out a su C# extern?

Otra idea es intentar pasar en un intptr en lugar de la clase en sí, o pasarla en un intptr ...

Creo que las estructuras se copian, no se pasan por referencia por defecto.

Honestamente apuñalando en la oscuridad, pero aún no tienes ninguna respuesta, así que espero que esto ayude ...

INETROP todavía está en la etapa de "It's Magic" para mí ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top