Как вызвать неуправляемую функцию C ++ с std :: vector в качестве параметра из C #?

У меня есть интерфейс C # и C ++ по соображениям производительности. Теперь я хотел бы вызвать функцию C ++, например:

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

Я хотел бы иметь функцию-оболочку C #, например:

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

Я мог бы передать плоский массив, например Point [], в неуправляемую DLL C ++, но проблема в том, что я не знаю, сколько памяти выделить, потому что я не знаю, сколько элементов вернет функция ...

Есть ли элегантный способ справиться с этим без проблем с утечками памяти?

Спасибо за вашу помощь!

Вениамин

Ответы на вопрос(4)

имый тип, такой как IEnumerable, и затем (вздыхает) копирует каждый элемент в ваш вектор, а затем вызывает PInvoke.

ку на языке 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 ++.

облемы с производительностью), можно было бы написать класс ссылок C ++ / CLI вокруг std :: vector <>. Таким образом, алгоритм c ++ может работать с типами c ++, а код C # может обращаться к одним и тем же данным без чрезмерного копирования.

Класс C ++ / CLI может реализовывать operator [] и Count, чтобы не полагаться на IEnumerable :: GetEnumerator ().

Решение Вопроса

которая ограничена классами не-C ++. Нетривиальные классы C ++ по существу не маршируются через слой PInvoke [1]. Вместо этого сделайте так, чтобы функция-обертка использовала более традиционную сигнатуру C, с которой PInvoke легко справиться

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

[1] Да, есть определенные случаи, когда вы можете избежать неприятностей, но это исключение, а не правило.

Ваш ответ на вопрос