首先,我想你應該改變C結構一點點:
typedef struct{
UINT cApples;
const apple *pApples;
UINT cLeaves;
const leaf *pLeaves;
} tree;
在C#的一面:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct Tree
{
internal uint cApples;
internal IntPtr pApples;
internal uint cLeaves;
internal IntPtr pLeaves;
}
您可以定義Leaf
和Apple
類似。然後你就可以填充它們在C#方如下:
private Tree CreateTree(Leaf[] leaves, Apple[] apples)
{
var result = new Tree();
result.cLeaves = (uint)leaves.Length;
result.cApples = (uint)apples.Length;
result.pLeaves = AllocateNativeMemory(leaves);
result.pApples = AllocateNativeMemory(apples);
return result;
}
private IntPtr AllocateNativeMemory<T>(T[] elements) where T : struct
{
int elementSize = Marshal.SizeOf(typeof(T));
IntPtr result = Marshal.AllocHGlobal(elements.Length * elementSize);
for (int i = 0; i < elements.Length; i++)
{
Marshal.StructureToPtr(
elements[i], new IntPtr((long)result + i * elementSize), false);
}
return result;
}
現在你可以通過CreateTree
方法來調用C面的方法的extern的結果。
備註:分配的內存應該被釋放;否則,你的應用程序將泄漏。如果您決定了C#方負責釋放分配的內存,你應該做到底,如下所示:
private static void FreeTree(Tree tree)
{
FreeNativeMemory<Leaf>(tree.pLeaves, tree.cLeaves);
FreeNativeMemory<Apple>(tree.pApples, tree.cApples);
}
private static void FreeNativeMemory<T>(IntPtr arrayPtr, uint arrayLen) where T : struct
{
int elementSize = Marshal.SizeOf(typeof(T));
for (uint i = 0; i < arrayLen; i++)
{
Marshal.DestroyStructure(new IntPtr((long)arrayPtr + i * elementSize), typeof(T));
}
Marshal.FreeHGlobal(arrayPtr);
}
爲了做到這樣的東西,你需要通過編組非託管數據類型爲結構指定一個順序佈局類型,並將該數組專門編組爲C樣式數組。查看MSDN文章「平臺調用教程」,特別是標有[「爲用戶定義的結構指定自定義封送」部分]的部分(https://msdn.microsoft.com/zh-cn/library/aa288468(v = vs。 71)的.aspx#pinvoke_custommarshaling)。 –
看看這個問題http://stackoverflow.com/questions/2240804/marshalling-what-is-it-and-why-do-we-need-it。 –
如果有人對這個過程更加熟悉,並且可以寫出完整的答案,歡迎您加入。 –