【问题标题】:Problem assigninging values to a struct in C++ to a structure passed from C#将值分配给 C++ 中的结构到从 C# 传递的结构的问题
【发布时间】:2010-12-26 13:36:30
【问题描述】:

我在 C# 中有一个函数,它将结构数组传递到用 C++ 编写的 DLL 中。该结构是一组整数,当我读出 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;
}

【问题讨论】:

    标签: c# c++ dll struct interopservices


    【解决方案1】:

    我找到了另一个问题的答案:How to marshall array of structs in C#?

    当编组显然默认是将参数编组为 In。否则,它们需要显式声明为 Out 或 In、Out。在明确指定我的代码后,示例现在可以工作了。

    感谢他的Skeetness 的回答,感谢antonmarkov 对MarshalAs 的曝光。

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

    【讨论】:

      【解决方案2】:

      来自MDSN article 编组数组:尝试在您的数组类型上设置以下属性。这通常用于从 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/

      【讨论】:

      • 好了,我们知道这与 C# 如何声明 extern 有关。
      • 我可以使用 LPArray 获得相同的结果,使用 SafeArray 或 ByValArray 会导致错误。使用另一个值会产生错误,指出数组只能使用前三种类型。
      【解决方案3】:

      您是否尝试将 ref/out 关键字添加到您的 C# extern?

      另一个想法是尝试传入一个 IntPtr 而不是类本身,或者将其传入 -as- 一个 IntPtr...

      我相信结构是复制的,而不是默认通过引用传递的。

      老实说,在黑暗中刺伤,但你还没有任何答案,所以希望这会有所帮助......

      Interop 对我来说仍处于“它的魔力”阶段...

      【讨论】:

      • 从行为看来,它是通过引用传递的。当我尝试使用 ref 时,我在 C++ 端得到了疯狂的值,就像这些值实际上是指针一样。如果我将接收类型更改为指向指针的指针,则会出现内存访问异常:(我即将将所有内容打包到一个 int 数组中并传递它,导致这个“魔术”让我感到沮丧。
      猜你喜欢
      • 2018-09-18
      • 2018-04-04
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      • 2013-04-12
      • 2015-01-03
      相关资源
      最近更新 更多