【问题标题】:Marshal an array of structs in pInvoke在 pInvoke 中编组结构数组
【发布时间】:2013-11-27 12:47:34
【问题描述】:

我在 C# 中有一个这样的结构:

[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct MyStruct
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
    public string StringValue;
    public uint IUintValue;
}

以及原生代码中对应的结构体

struct MyStruct
{
    char StringValue[17];
    ulong UintValue;
}

我的目标是使用 pinvoke 将这个结构的数组从 c# 端传递到 c++(本机端)。 这是我在 c# 中的使用方法

[DllImport(@"MyLibrary.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern int SendArray([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]ref MyStruct[] arr, int recordsCount);

调用代码是:

var array = new MyStruct[10];
//initialize
SendArray(ref array, array.Length);

在本机方面,我有以下函数签名:

extern "C" __declspec(dllexport) int SendArray(MyStruct** Arr, int recordsCount);

而且它似乎只适用于数组中的第一个元素。在 c++ 方面,我得到了这个数组,但只有第一个元素被正确编组。其余的似乎都是垃圾。

我的错误在哪里?

【问题讨论】:

  • 那绝对应该是 MyStruct* Arr,由 C# 端的 MyStruct[] 匹配 without ref。添加一些测试代码并确保 C 端的 sizeof(MyStruct) 与 C# 端的 Marshal.SizeOf(MyStruct) 匹配。如果不是,那么第二个和后续元素将是垃圾。
  • C#字符串和char[17]一样吗?
  • 如果大小不匹配,为什么第一个元素被正确编组?

标签: c# c++ arrays pinvoke marshalling


【解决方案1】:

您的 C++ 代码没有收到结构数组。它接收指向结构的指针数组。把 C++ 代码改成这样:

int SendArray(MyStruct* Arr, int recordsCount);

或许

int SendArray(MyStruct Arr[], int recordsCount);

然后你的 p/invoke 应该是

[DllImport(...)]
public static extern int SendArray([In] MyStruct[] arr, int recordsCount);

我也怀疑Pack=8。你确定吗?

【讨论】:

  • 我已经尝试了您的两种解决方案,但不幸的是它们都不适合我 =/
  • 顺便说一句,我应该明确设置 [In] 属性吗?这是默认的,不是吗?
  • 我认为你可以省略它。我想在这里明确一点:stackoverflow.com/questions/14366066/…
  • 是的,你的答案是正确的。似乎在 c++ 方面有一个错误。(在收到一个有效的数组后,他们设法以某种方式破坏它)我说“他们”是因为我只负责 .net 部分的工作。因为这个=S idiots :D 杀死了将近 2 天
  • 据我了解该链接到另一个问题,它仅适用于属性的输入/输出组合。在将结构从非托管恢复到托管时强制复制。对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多