如何调用非托管 C++ C# 中以 std::vector 作为参数的函数?
出于性能原因,我有一个 C# 前端和一个 C++ 后端。 现在我想调用一个 C++ 函数,例如:
void findNeighbors(Point p, std::vector<Point> &neighbors, double maxDist);
我想要一个 C# 包装函数,例如:
List<Point> FindNeigbors(Point p, double maxDist);
我可以将像 Point[] 这样的平面数组传递给非托管 C++ dll,但问题是,我不知道要分配多少内存,因为我不知道函数将返回的元素数量...
是否有一种优雅的方法来处理这个问题,而不会遇到内存泄漏的问题?
感谢您的帮助!
本杰明
I have a C# front end and a C++ backend for performance reasons.
Now I would like to call a C++ function like for example:
void findNeighbors(Point p, std::vector<Point> &neighbors, double maxDist);
What I'd like to have is a C# wrapper function like:
List<Point> FindNeigbors(Point p, double maxDist);
I could pass a flat array like Point[] to the unmanaged C++ dll, but the problem is, that I don't know how much memory to allocate, because I don't know the number of elements the function will return...
Is there an elegant way to handle this without having troubles with memory leaks?
Thanks for your help!
Benjamin
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这里最好的解决方案是用 C 语言编写一个仅限于非 C++ 类的包装函数。重要的 C++ 类本质上是通过 PInvoke 层不可编组的 [1]。相反,让包装函数使用更传统的 C 签名,该签名很容易针对
[1] 进行 PInvoke。是的,在某些情况下您可以摆脱它,但这是例外,而不是规则。
The best solution here is to write a wrapper function in C which is limited to non-C++ classes. Non-trivial C++ classes are essentially unmarshable via the PInvoke layer [1]. Instead have the wrapper function use a more traditional C signature which is easy to PInvoke against
[1] Yes there are certain cases where you can get away with it but that's the exception and not the rule.
阻抗不匹配严重。您必须用 C++/CLI 语言编写包装器,以便可以构造向量。另一个问题是 Point,您的 C++ 声明与它的托管版本不兼容。您的代码应该与此类似,将其从 CLR 节点添加到类库项目中。
请注意复制集合的成本,这会很快消除您可能从用本机 C++ 编写算法中获得的性能优势。
The impedance mismatch is severe. You have to write a wrapper in the C++/CLI language so that you can construct a vector. An additional problem is Point, your C++ declaration for it is not compatible with the managed version of it. Your code ought to resemble this, add it to a class library project from the CLR node.
Do note the cost of copying the collection, this can quickly erase the perf advantage you might get out of writing the algorithm in native C++.
为了减少复制的开销(如果这确实会导致性能问题),可以围绕 std::vector<> 编写 C++/CLI 引用类。这样,C++ 算法就可以在 C++ 类型上运行,并且 C# 代码可以访问相同的数据,而无需进行过多的复制。
C++/CLI 类可以实现operator[] 和Count 以避免依赖IEnumerable::GetEnumerator ()。
In order to reduce overhead from copying (if that does cause performance problems) it would be possible to write a C++/CLI ref class around std::vector<>. That way the c++ algorithm can work on c++ types and C# code can access the same data without excessive copying.
The C++/CLI class could implement operator[] and Count in order to avoid relying on IEnumerable::GetEnumerator ().
或者用 C++/CLI 编写包装器。让它采用符合 CLS 的类型,例如 IEnumerable,然后(叹气)将每个元素复制到向量中,然后调用 PInvoke。
Or write your wrapper in C++/CLI. Have it take a CLS-compliant type such as IEnumerable and then (sigh) copy each element into your vector, then call the PInvoke.