我正在尝试将以下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而失败。
我希望尽可能少的PInvoke调用将整个树结构从C ++转移到C#,以提高速度。这就是为什么在执行任何代码之前,我的整个树都被展平为一个列表。每个节点仍然有一个指向其父节点和子节点的指针,因此很容易重构它。如果它更容易,我也可以通过根节点。
以下是我的问题:
1)是否可能包含其他向量的对象的编组向量?我应该使用数组或其他东西使我的C ++类更简单吗?
2)有没有办法通过GetFileSystemNodes
传递节点向量而不将向量中的所有内容移动到数组参数?
3)编写C#结构的正确方法是什么,它与我的C#结构相匹配?
答案 0 :(得分:0)
可以这样做,我建议使用SWIG。 SWIG使C ++和其他语言(包括C#)之间的互操作变得更加容易。它内置了对处理某些C ++ STL容器的支持,例如vector。
是的,SWIG可以处理对象的向量,你只需要在接口文件中构建它们。