2

C++ で記述された DLL に構造体の配列を渡す C# の関数があります。構造体は int のグループであり、DLL 内のデータを読み取ると、すべての値が正常に出力されます。ただし、C++ から要素に書き込もうとすると、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;
}
4

3 に答える 3

1

配列のマーシャリングに関するMDSN の記事から: 配列型に次の属性を設定してみてください。これは通常、C++ から C# を呼び出すために使用されますが、更新された値を C# に戻すために必要になる場合もあります。

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

成功した双方向マーシャリングの例については、次の記事も参照してください。

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

于 2009-12-14T20:22:57.857 に答える
0

別の質問に投稿された回答を見つけました: C# で構造体の配列をマーシャリングする方法は?

明らかにマーシャリングするとき、デフォルトはパラメータを In としてマーシャリングすることです。それ以外の場合は、Out または In, Out として明示的に宣言する必要があります。私のコードを明示的に指定した後、例が機能するようになりました。

答えてくれた彼のSkeetnessと元帥に触れてくれたantonmarkovに感謝します。

private static extern int PassSomeStructs(int count, [In, Out] Box[] boxes, [In, Out] Spot[] points);
于 2009-12-14T21:46:32.177 に答える
0

C# の extern に ref/out キーワードを追加してみましたか?

別のアイデアは、クラス自体の代わりに IntPtr を渡すか、IntPtr として渡すことです...

デフォルトでは参照渡しではなく、構造体がコピーされると思います。

正直なところ、暗闇を突き刺していますが、まだ答えがありません。うまくいけば、これが役に立ちます...

相互運用性は、私にとってまだ「魔法のような」段階にあります...

于 2009-12-14T20:16:38.477 に答える