如何使用DLL(用C编写)在C#中创建结构数组?

如何使用DLL(用C编写)在C#中创建结构数组?,c#,c,visual-studio,dll,dllexport,C#,C,Visual Studio,Dll,Dllexport,我想用数据填充结构,以便将其传递给DLL函数。这些结构在C#和C实现中都是相似的。例如(在C中): 我想在C#上创建一个树结构,用苹果和树叶填充它,然后将它发送到DLL上的函数 如何操作?首先,我认为您应该稍微更改C结构: typedef struct{ UINT cApples; const apple *pApples; UINT cLeaves; const leaf *pLeaves; } tree; 在C侧: 您可以类似地定义Leaf和Apple。然后

我想用数据填充结构,以便将其传递给DLL函数。这些结构在C#和C实现中都是相似的。例如(在C中):

我想在C#上创建一个树结构,用苹果和树叶填充它,然后将它发送到DLL上的函数


如何操作?

首先,我认为您应该稍微更改C结构:

typedef struct{
    UINT cApples;
    const apple *pApples;
    UINT cLeaves;
    const leaf *pLeaves;
} tree;
在C侧:

您可以类似地定义
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;
}
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文章“平台调用教程”,特别是标记为的部分。查看问题。如果有人更熟悉此过程并能写出完整答案,欢迎您加入该代表。在尝试pinvoke之前,请先使用C。你会情不自禁地发现自己遇到了大问题。就像C代码不知道结构中存储了多少元素一样。还有棘手的内存管理问题,谁负责释放这些阵列的内存?这些问题在pPoCKE中不会变好。如果我理解WEL,在像你这样的情况下,我就开发了一个C++的DLL包装器。这个“技术”允许你使用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;
}
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);
}