簡體   English   中英

如何從C#中使用std :: vector作為參數調用非托管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.

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