[英]How to call an unmanaged C++ function with a std::vector<>::iterator as parameter from C#?
[英]Howto call an unmanaged C++ function with a std::vector as parameter from C#?
由於性能原因,我有一個C#前端和一個C ++后端。 現在,我想調用一個C ++函數,例如:
void findNeighbors(Point p, std::vector<Point> &neighbors, double maxDist);
我想要的是一個C#包裝函數,例如:
List<Point> FindNeigbors(Point p, double maxDist);
我可以將像Point []這樣的平面數組傳遞給不受管理的C ++ dll,但是問題是,我不知道要分配多少內存,因為我不知道該函數將返回的元素數...
有沒有一種優雅的方式來解決此問題而又不會造成內存泄漏?
謝謝你的幫助!
本傑明
最好的解決方案是用C語言編寫包裝函數,該函數僅限於非C ++類。 通過PInvoke層[1],非平凡的C ++類基本上是不可拆的。 取而代之的是,包裝函數使用更傳統的C簽名,很容易針對
void findNeigborsWrapper(
Point p,
double maxDist,
Point** ppNeighbors,
size_t* pNeighborsLength)
[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;
}
};
}
請注意復制集合的成本,這可以快速消除您可能無法使用本機C ++編寫算法而獲得的性能優勢。
為了減少復制的開銷(如果確實會導致性能問題),可以在std :: vector <>周圍編寫一個C ++ / CLI ref類。 這樣,c ++算法就可以在c ++類型上工作,並且C#代碼可以訪問相同的數據而無需過度復制。
C ++ / CLI類可以實現operator []和Count,以避免依賴IEnumerable :: GetEnumerator()。
或用C ++ / CLI編寫包裝。 讓它采用兼容CLS的類型,例如IEnumerable,然后(嘆氣)將每個元素復制到向量中,然后調用PInvoke。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.