Как может я Маршалл вектор <интервал> от C++ dll к приложению C#?

У меня есть функция C++, которая производит список прямоугольников, которые интересны. Я хочу смочь вытащить тот список из библиотеки C++ и назад в приложение C#, которое называет его.

До сих пор я кодирую прямоугольники как так:

struct ImagePatch{ 
   int xmin, xmax, ymin, ymax;
}

и затем кодирование некоторых векторов:

void MyFunc(..., std::vector& rectanglePoints){
   std::vector patches; //this is filled with rectangles
   for(i = 0; i < patches.size(); i++){
       rectanglePoints.push_back(patches[i].xmin);
       rectanglePoints.push_back(patches[i].xmax);
       rectanglePoints.push_back(patches[i].ymin);
       rectanglePoints.push_back(patches[i].ymax);
   }
}

Заголовок для взаимодействия с C# похож (и работает на набор других функций):

extern "C" {
    __declspec(dllexport) void __cdecl MyFunc(..., std::vector& rectanglePoints);
}

Есть ли некоторые ключевые слова или другие вещи, которые я могу сделать для получения того набора прямоугольников? Я нашел эту статью для маршалинга объектов в C#, но это кажется слишком сложным и слишком underexplained. Действительно ли вектор целых чисел является правильным способом сделать это или является там некоторым другим приемом или подходом?

8
задан mmr 30 April 2010 в 20:47
поделиться

2 ответа

STL - это библиотека, специфичная для C ++, поэтому вы не можете напрямую передать ее как один объект в C #.

Единственное, что гарантировано в std :: vector - это то, что & v [0] указывает на первый элемент, и все элементы лежат в памяти линейно (другими словами, это как массив C с точки зрения структуры памяти)

Таким образом, маршалинг в виде массива int ... что не должно быть сложно - в сети есть много примеров.

Добавлено

Предполагая, что вы передаете данные только из C ++ в C #:

C # не может обрабатывать векторный объект C ++, поэтому не пытайтесь передать его по ссылке: вместо этого ваш код C ++ должен возвращать указатель на массив ints ...

Если вы не собираетесь использовать эту функцию из нескольких потоков, вы можете использовать статическое хранилище:

int *getRects(bool bClear)
{
    static vector<int> v; // This variable persists across invocations
    if(bClear)
    {
        v.swap(vector<int>());
    }
    else
    {
        v.clear();
        // Fill v with data as you wish
    }

    return v.size() ? &v[0] : NULL;
}

вызовите getRects (true), если возвращаемые данные значительны по размеру, поэтому вы освобождаете память в v.

Для простоты, вместо того, чтобы передавать размер векторных данных, просто поместите контрольное значение в конце (например, -1), чтобы код C # мог определить, где заканчиваются данные.

4
ответ дан 5 December 2019 в 23:14
поделиться

Я уверен, что вы не сможете этого сделать. Вы должны быть в состоянии перевести код C++ непосредственно в класс C#, поэтому вам, по крайней мере, придется повторить внутреннее устройство класса вектора, чтобы правильно его маршаллировать. Я также уверен, что вы не сможете перемещать ссылки через границу, вам придется использовать IntPtr (необработанные указатели). Подход, который, как я знаю, работает, заключается в маршаллировании необработанного массива структур.

0
ответ дан 5 December 2019 в 23:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: