从非托管代码返回分配的值到托管代码

3
我想要做以下事情: 调用未托管方法,使其返回分配的MyStruct[]类型的数组。
C代码示例:
MyStruct[] foo(int size)
{
   Mystruct* st = (MyStruct*)malloc(size * sizeof(MyStruct));
   return st;
}

如何实现C#调用方法?
谢谢!

我正在尝试使用已编写在unmanaged.dll中的现有算法,并希望获得结果 :) - Sergey Kucher
那段代码没有任何有用的功能。最好使用Marshal.AllocCoTaskMem()。 - Hans Passant
这是一段不够清晰的代码示例。 - Sergey Kucher
3个回答

5
System.Runtime.InteropServices命名空间中,Marshal类有很多方法可以帮助您将数据从非托管代码传输到托管代码或者相反。
您需要声明您的本地方法:
[DllImport("myclib.dll")]
public static extern IntPtr Foo(Int32 size);

同时,您的C结构作为托管值类型(您可以在字段上使用属性来控制它们在进行封送时如何映射到本机内存):
[StructLayout(LayoutKind.Sequential)]
struct MyStruct {
  public Char Character;
  public Int32 Number;
}

然后你可以使用Marshal.PtrToStructure将数组的每个元素转换为托管值:
var n = 12;
var pointer = Foo(n);
var array = new MyStruct[n];
var structSize = Marshal.SizeOf(typeof(MyStruct));
for (var i = 0; i < n; ++i) {
  array[i] = (MyStruct) Marshal.PtrToStructure(pointer, typeof(MyStruct));
  pointer += structSize;
}

请注意,您在C代码中使用malloc来分配内存。但是C#无法释放该内存,因此您需要提供另一种方法来释放已分配的内存。

1

我在那里没有找到如何返回已声明结构的数组类型。 - Sergey Kucher
这并没有直接的解决方案,解决方法可能是传递数组并让库填充它并将其发送回来。如此处所述:http://answers.unity3d.com/questions/132083/returning-a-byte-array-from-objc-to-c-script-on-io.html - Zenwalker

1

请参考此线程,其中包含有关如何将从C++动态分配的结构以数组形式返回到C#的一些信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接