c# - 将数据从 C++ 传递到 C# 的最有效方法

标签 c# c++ pinvoke memcpy

我正在寻找将大量数据从 C++(结构或值类?)传输到 C# 类的最佳方法,并尽可能少地复制数据。在下面的示例代码中,我有一个可能非常大(10+ 百万)的 SubClass 对象 vector 。所以我想尽可能避免数据复制。

我应该/我可以先在 GC 中分配对象并直接在 C++ 中使用它们而忘记 native C++ 结构吗? (性能是我关心的问题。)

或者,是否有一些技巧可以利用 C++ 中分配的内容而不会导致数据复制?

这是我想用作托管和非托管代码之间传输的内容的示例。

#include <string>
#include <vector>
struct SubClass {
    std::string DataItem1;
    // lots more here
    std::string DataItem50;
};

struct Sample {
    int IntValue;
    std::string StringValue;
    std::vector<std::string> SmallList;
    std::vector<SubClass> HugeList;
};

如果我可以避免陷入 pinvoke 和 COM 类的杂草,我会更喜欢它。

最佳答案

遵循 Unity(使用 C#)的示例,Native plugin example使用 GC 句柄将数据从 C# 传输到 C++。我们可以尝试相反的方法,将数据从 C++ 发送到 C#。
固定一个 C# 变量以允许更快的复制。

using System;
using System.Collections;
using System.Runtime.InteropServices;
// vertices is a Vector3[], where Vector3 is a struct 
// of 3 floats using a sequential layout attribute
void test(){
GCHandle gcVertices = GCHandle.Alloc (vertices, GCHandleType.Pinned); 
}
使用编码(marshal)处理将句柄传输到 C++。你不得不复制一些东西是不可避免的。这里复制一个指针应该就足够了。更多关于 Microsoft 编码的信息 doc .
[DllImport("your dll")]
private static extern void SendHandle(IntPtr vertexHandle, int vertexCount);
SendHandle(gcVertices, vertices.Length);
在 C++ 中,您将收到作为指向您选择的 C++ 类型的指针类型的句柄。在这种情况下,vertices是 3 个浮点数的结构列表。引用代码决定使用float * .您只需要根据指向的类型正确地进行指针运算,包括 void * 的情况。 .
extern "C" __decl(dllexport) void SendHandle(float* vertices, int vertexCount);
这里的示例代码直接从指针复制数据,但您也可以写入指针的位置。
for (int i = 0 ; i < vertexCount; i++)
{
   // read from C# heap
   float x = vertices[0];
   float y = vertices[1];
   float z = vertices[2];

   // write to C# heap
   *vertices = sqrt(x);
   *(vertices + 1) = sqrt(y);
   *(vertices + 2) = sqrt(z);

   vertices += 3; // because it is a list of struct of 3 floats
}
从 C# 端清除固定句柄以恢复垃圾收集器。
gcVertices.Free();
至于字符串,我相信互操作库有一个为您处理指针算术和复制的实现。您可以直接在公开的导出函数中使用字符串类型,只要您指定如何使用 MarshalAs 对其进行编码(marshal)处理即可。 C# 中的属性和 C++ 中的库,如果您不转换为 C 类型 char * .

关于c# - 将数据从 C++ 传递到 C# 的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28059239/

相关文章:

c# - 使用从 C# 到非托管驱动程序的嵌入式指针编码结构

c# - 从具有模式的目录中获取文件

c# - 如何处理在 RichTextBox 中单击超链接的事件

c++ - boost.python 中没有

c# - 将非托管数据映射到 .NET 中的托管结构

c# - Pinvoke C# : delegated function cause crash

c# - 无法定位 Android 应用中内存泄漏的原因

c# - 对 Silverlight 类库的引用

c++ - 等价于 Matlab 的 sum(A)?

c++ - 在 Windows 中编译 Faster RNNLM 的问题