我如何马歇尔递归结构到c锋利?
-
18-09-2019 - |
题
我有一个非托管结构我想编组至c尖锐看起来基本上是这样的:结果
struct MyStruct{
/* ... some stuff ... */
int numChilds;
MyStruct *childs;
}
我认为,我必须写一个自定义编组,但我不知道如何继续。
解决方案
我喜欢用这样的设置时,我并不需要直接指标儿童:
struct MyStruct
{
/* ... some stuff ... */
int numChilds;
IntPtr childData;
public IEnumerable<MyStruct> Children
{
get
{
int elementSize = Marshal.SizeOf(typeof(MyStruct));
for (int i = 0; i < this.numChilds; i++)
{
IntPtr data = new IntPtr(this.childData.ToInt64() + elementSize * i);
MyStruct child = (MyStruct)Marshal.PtrToStructure(data, typeof(MyStruct));
yield return child;
}
}
}
}
如果您的做的需要直接索引孩子,最简单的办法是创建一个方法GetChild
(如下图所示)。更难的方法是创建一个实现IList<MyStruct>
一个辅助/包装类。实例将从Children
财产归还,其内部会通过调用GetChild
方法工作。这是作为练习留给读者自己需要它。
public MyStruct GetChild(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("index", "The index must be >= 0.");
if (index >= this.numChilds)
throw new ArgumentException("The index must be less than the number of children", "index");
int elementSize = Marshal.SizeOf(typeof(MyStruct));
IntPtr data = new IntPtr(childData.ToInt64() + elementSize * index);
MyStruct child = (MyStruct)Marshal.PtrToStructure(data, typeof(MyStruct));
return child;
}
其他提示
如果你只想将它传递给一些非托管功能,你可以只使用不安全的代码和stackalloc /修复阵列来获得一个指向对象的数组。
unsafe struct Foo
{
public int value;
public int fooCount;
public Foo* foos;
}
[DllImport("dll_natv.dll")]
static extern void PrintFoos(Foo f);
public unsafe static void Main()
{
Foo* foos = stackalloc Foo[10];
for (int i = 0; i < 10; ++i)
foos[i].value = i;
Foo mainFoo = new Foo();
mainFoo.fooCount = 10;
mainFoo.value = 100;
mainFoo.foos = foos;
PrintFoos(mainFoo);
}
不隶属于 StackOverflow