2010-09-22 64 views
2

出於性能原因,我有一個C#前端和一個C++後端。 現在我想調用C++之類的函數,例如:Howto使用std :: vector作爲C#參數調用非託管C++函數?

void findNeighbors(Point p, std::vector<Point> &neighbors, double maxDist); 

我想有像一個C#包裝函數:

List<Point> FindNeigbors(Point p, double maxDist); 

我能通過一個平面數組像點[]到非託管的C++ DLL,但問題是,我不知道分配多少內存,因爲我不知道函數將返回的元素數量...

有沒有一個優雅如何處理這個問題,而不會造成內存泄漏問題?

感謝您的幫助!

本傑明

回答

3

最好這裏的解決方案是用C來寫一個包裝函數被限制於非C++類。非平凡的C++類實質上是通過PInvoke層[1]不可編組的。相反,具有包裝功能使用更傳統的C簽名這是很容易的PInvoke對

void findNeigborsWrapper(
    Point p, 
    double maxDist, 
    Point** ppNeighbors, 
    size_t* pNeighborsLength) 

[1]是有一定的情況下,你可以擺脫它,但是這是例外,而不是規則。

1

阻抗不匹配很嚴重。你必須用C++/CLI語言編寫一個包裝器,以便構建一個向量。另一個問題是Point,你的C++聲明與它的託管版本不兼容。你的代碼應該與此類似,將它添加到CLR節點的類庫項目中。

#include <vector> 

using namespace System; 
using namespace System::Collections::Generic; 

struct Point { int x; int y; }; 
void findNeighbors(Point p, std::vector<Point> &neighbors, double maxDist); 

namespace Mumble { 

    public ref class Wrapper 
    { 
    public: 
     List<System::Drawing::Point>^ FindNeigbors(System::Drawing::Point p, double maxDist) { 
      std::vector<Point> neighbors; 
      Point point; point.x = p.X; point.y = p.Y; 
      findNeighbors(point, neighbors, maxDist); 
      List<System::Drawing::Point>^ retval = gcnew List<System::Drawing::Point>(); 
      for (std::vector<Point>::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { 
       retval->Add(System::Drawing::Point(it->x, it->y)); 
      } 
      return retval; 
     } 
    }; 
} 

請注意複製收集成本,這可以快速擦除PERF優勢,你可能會失去在編寫本地C++的算法。

0

或者用C++/CLI編寫你的包裝器。讓它採用符合CLS的類型(如IEnumerable),然後(嘆氣)將每個元素複製到您的矢量中,然後調用PInvoke。

0

爲了減少從複製的開銷(如果這樣做會導致性能問題)將有可能寫周圍STD一個C++/CLI引用類::矢量<>。這樣C++算法可以在C++類型上工作,並且C#代碼可以訪問相同的數據而不會過度複製。

C++/CLI類可以實現operator []和Count以避免依賴於IEnumerable :: GetEnumerator()。

相關問題