编组包含std :: vector

时间:2016-12-16 14:56:59

标签: c# c++ marshalling

我正在尝试将以下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()以通过向量并将所有内容添加到数组nodesresults将有一堆看起来像内存地址的数字(虽然我不知道他们是否是垃圾还是不垃圾),但Marshal.PtrToStructure<CFileNode>(ptr)因AccessViolationException而失败。

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

以下是我的问题:

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

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

3)编写C#结构的正确方法是什么,它与我的C#结构相匹配?

1 个答案:

答案 0 :(得分:0)

可以这样做,我建议使用SWIG。 SWIG使C ++和其他语言(包括C#)之间的互操作变得更加容易。它内置了对处理某些C ++ STL容器的支持,例如vector。

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