У меня есть функция 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. Действительно ли вектор целых чисел является правильным способом сделать это или является там некоторым другим приемом или подходом?
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 # мог определить, где заканчиваются данные.
Я уверен, что вы не сможете этого сделать. Вы должны быть в состоянии перевести код C++ непосредственно в класс C#, поэтому вам, по крайней мере, придется повторить внутреннее устройство класса вектора, чтобы правильно его маршаллировать. Я также уверен, что вы не сможете перемещать ссылки через границу, вам придется использовать IntPtr (необработанные указатели). Подход, который, как я знаю, работает, заключается в маршаллировании необработанного массива структур.