Question

J'ai une fonction en C # qui passe un tableau de structures dans une DLL écrite en C ++. La structure est un groupe d'INTS et lorsque j'ai lu les données dans la DLL, toutes les valeurs sortent bien. Cependant, si j'essaie d'écrire aux éléments de C ++, les valeurs n'apparaissent jamais lorsque j'essaie de lire puis de retour en 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;
}
Était-ce utile?

La solution 3

J'ai trouvé la réponse publiée sur une autre question: Comment maréter la gamme de structures en C #?

Lorsque le rassemblement apparemment, la valeur par défaut est de rassembler les paramètres comme dans. Sinon, ils doivent être déclarés explicitement comme sorties ou dans la sortie. Après avoir précisé que mon code explicite, l'exemple fonctionne maintenant.

Merci à son Skeetness pour la réponse et pour Antonmarkov pour l'exposition aux marshalas.

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

Autres conseils

De un Article MDSN Sur les tableaux de maréchal: essayez de définir l'attribut suivant sur vos types de tableaux. Ceci est normalement utilisé pour appeler C # à partir de C ++, mais il peut également être nécessaire de remettre des valeurs mises à jour 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);

Voir également cet article pour un exemple de marshalling bidirectionnel réussi:

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

Avez-vous essayé d'ajouter le mot-clé ref / out à votre C # extern?

Une autre idée est d'essayer de passer dans un Intptr au lieu de la classe elle-même, ou de la transmettre en - un intptr ...

Je crois que les structures sont copiées, non transmises par référence par défaut.

Honnêtement poignardant dans le noir, mais vous n'avez pas encore de réponses, alors j'espère que cela aide ...

Interop est toujours dans la scène "c'est magique" pour moi ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top