开发者

Problem assigninging values to a struct in C++ to a structure passed from C#

开发者 https://www.devze.com 2022-12-14 12:29 出处:网络
I have a function in C# that is passing an array of structures into a DLL written in C++. The struct is a group of ints and when I read out the data in the DLL all the values come out fine. However if

I have a function in C# that is passing an array of structures into a DLL written in C++. The struct is a group of ints and when I read out the data in the DLL all the values come out fine. However if I try to write to the elements from C++ the values never show up when I try to read then back in 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;
}


From an MDSN article on marshalling arrays: try setting the following attribute on your array types. This is normally used for calling into C# from C++, but it may also be required for getting updated values back into C#.

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

Also see this article for an example of successful two-way marshalling:

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


Have you tried adding the ref/out keyword to your C# extern?

Another idea is try passing in an IntPtr instead of the class itself, or passing it in -as- an IntPtr...

I believe that structs are copied, not passed by reference by default.

Honestly stabbing in the dark, but you don't have any answers yet, so hopefully this helps...

Interop is still in the "it's magic" stage for me...


I found the answer posted to another question: How to marshall array of structs in C#?

When marshaling apparently the default is to marshal the parameters as In. Otherwise they need to be explicitly declared as Out or In, Out. After specifying that explicitly my code the example now works.

Thanks to his Skeetness for the answer and to antonmarkov for the exposure to the MarshalAs.

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

精彩评论

暂无评论...
验证码 换一张
取 消