编组包含std :: vector的结构

Marshalling array of structures that contain a std::vector

本文关键字:vector 结构 std 包含      更新时间:2023-10-16

我试图将以下C 类的向量元用到C#中:

class CFileNode
{
  private:
    std::string m_name;
    std::vector<CFileNode*> m_children;
    bool m_isDirectory;
    CFileNode* m_parent;
};

和:

extern DATAACCESSLAYERDLL_API size_t __stdcall Get_FileSystemNodeCount()
{
    // GetFileNodeList() returns a std::vector<CFileNode*>&
    return CFileSystem::GetFileNodeList().size();
}
extern DATAACCESSLAYERDLL_API void __stdcall Get_FileSystemNodes(size_t count, CFileNode** nodes)
{
    nodes = CFileSystem::GetFileNodeList().data();
}

和c#:

[SuppressUnmanagedCodeSecurity]
[DllImport("MyDll.dll")]
static private extern int Get_FileSystemNodeCount();
[SuppressUnmanagedCodeSecurity]
[DllImport("MyDll.dll")]
static private extern void Get_FileSystemNodes(int count, [In,Out] IntPtr[] outNodes);

和我的结构:

[StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
public struct CFileNode
{
    [MarshalAs(UnmanagedType.LPStr)]
    string m_name;
    [MarshalAs(UnmanagedType.SafeArray)]
    IntPtr[] m_children;
    [MarshalAs(UnmanagedType.Bool)]
    bool m_isDirectory;
    [MarshalAs(UnmanagedType.LPStruct)]
    IntPtr m_parent;
}

我在哪里使用:

int count = Get_FileSystemNodeCount();
IntPtr[] results = new IntPtr[count];
Get_FileSystemNodes(count, results);
foreach (IntPtr ptr in results)
{
    m_fileSystemNodes.Add(Marshal.PtrToStructure<CFileNode>(ptr));
}

在当前状态下,IntPtr[] results只是一个很大的零数组。如果我修改c GetFileSystemNodes()以通过向量并将所有内容添加到数组nodes,则results将具有看起来像内存地址的数字(尽管我不知道它们是否是垃圾),但是Marshal.PtrToStructure<CFileNode>(ptr)会失败。AccessViolationException。

我想以尽可能少的速度调用将整个树结构从C 转移到C#。这就是为什么在执行此代码的任何一个代码之前,我的整棵树都被扁平化为列表。每个节点仍然都有指向其父母和子女的指针,因此很容易重建它。如果使它变得更容易,我也可以通过根节点。

这是我的问题:

1)是否可以编组包含其他向量的对象的向量?我应该使用数组或其他内容使我的C 类更简单吗?

2)有没有办法通过GetFileSystemNodes传递节点向量而不将向量中的所有内容移至数组参数?

3)编写我的C#struct的正确方法是什么与我的C 匹配?

这可以完成,我建议使用swig。SWIG在C 和其他语言(包括C#)之间进行互动要容易得多。它已建立支持处理某些C STL容器,例如向量。

是的,SWIG可以处理对象的向量,您只需在接口文件中构建它们即可。