![](/img/trans.png)
[英]Most efficient way in adding identity column to a datatable with data in C#
[英]Most efficient way to pass data from C++ to C#
我正在尋找將大量數據從 C++(結構或值類?)傳輸到 C# 類的最佳方法,並盡可能少地復制數據。 在下面的示例代碼中,我有一個可能非常大(10+ 百萬)的 SubClass 對象向量。 所以我想盡可能避免數據復制。
我應該/我可以先在 GC 中分配對象並直接在 C++ 中使用它們而忘記本機 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#)的示例,本機插件示例使用 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);
}
使用封送處理將句柄傳輸到 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();
至於字符串,我相信互操作庫有一個為您處理指針算術和復制的實現。 您可以直接在公開的導出函數中使用字符串類型,只要您指定如何使用 C# 中的MarshalAs
屬性和 C++ 中的庫(如果您不轉換為 C 類型char *
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.