繁体   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