簡體   English   中英

將數據從 C++ 傳遞到 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM