В настоящее время я разрабатываю оболочку для библиотеки C++, поэтому ее можно использовать в MATLAB. Я хочу, чтобы мои объекты C++ были в MATLAB, чтобы пользователь мог что-то с ними делать. На самом деле я бросаю те C++ объекты в void *
потому что MATLAB поддерживает только заголовки C. Эти функции C выглядят следующим образом:
__declspec(dllexport) void *getPtr (int someArgument);
В MATLAB я называю такие функции:
ptr = calllib('LibName', 'getPtr', 42);
В MATLAB ptr теперь является <1x1 lib.pointer>
. Я ничего не могу с этим сделать, чтобы передать его другой функции C, например:
__declspec(dllexport) int doSomethingWithPtr (void *ptr);
Поэтому я result = calllib('LibName', 'doSomethingWithPtr', ptr);
в MATLAB, который отлично работает и выполняет эту функцию с указателем как аргументом. (Я отлаживал код C, а указатель такой же, как тот, который возвращался из getPtr
.
Для моей функции C требуется более одного указателя для работы, как это предусмотрено библиотекой C++. Я уже передал числовые данные в матрицах MATLAB в C, которые отлично работают с типом C mxArray
(см. Http://www.mathworks.de/de/help/matlab/apiref/mxarray.html). Для передачи нескольких указателей на CI был сконструирован массив MATLAB lib.pointer
следующим образом:
A = [];
for i = 1:10
ptr = calllib('LibName', 'getPtr', i);
A = [A, ptr];
end
И я __declspec(dllexport) int doSomethingWithPtrArray (mxArray *ptrarr);
другую функцию C (__declspec(dllexport) int doSomethingWithPtrArray (mxArray *ptrarr);
) в MATLAB:
ptr = calllib('LibName', 'doSomethingWithPtrArray', A);
Внутри функции C я получаю правильные размеры массива с помощью mxGetN(ptrarr)
и mxGetM(ptrarr)
. Я также могу получить указатель данных с помощью:
void *mexPtr = mxGetData(ptrarr);
Проблема в том, что mexPtr
и следующие указатели указывают на местоположения в памяти, которую я даже не выделял и не знал раньше. Возможно, MATLAB делает некоторую интеллектуальную упаковку при вызове функции с void *
и не делает этого, когда я передаю массив. (Я думаю, что получаю адреса в lib.pointer
оболочки MATLAB lib.pointer
?)
У кого-нибудь есть ключ (или обходной путь), как я получаю правильные указатели из mxArray, поэтому я могу сразу оценить несколько указателей?
Поскольку я не нашел "красивого" решения, я построил вспомогательный метод в C++, который позволяет мне создать собственный вектор:
void *buildClassifierVectorBase(void *vector, void *classifier)
{
typedef IClassifierManager<input_dtype, feature_dtype, annotation_dtype> class_man_t;
std::vector<std::shared_ptr<class_man_t>> *classMgrs;
if (vector == nullptr)
{
classMgrs = new std::vector<std::shared_ptr<class_man_t>>();
}
else
{
classMgrs = static_cast<std::vector<std::shared_ptr<class_man_t>> *>(vector);
}
class_man_t *cls = static_cast<class_man_t *>(classifier);
classMgrs->push_back(std::shared_ptr<class_man_t>(cls));
return static_cast<void *>(classMgrs);
}
Этот метод, который я могу использовать в MATLAB для создания этого вектора указателей, таких как:
ptr1 = calllib('LibName', 'getPtr', 42);
ptr2 = calllib('LibName', 'getPtr', 43);
ptr3 = calllib('LibName', 'getPtr', 44);
vector = calllib('LibName', 'buildClassifierVectorBase', libpointer, ptr1);
vector = calllib('LibName', 'buildClassifierVectorBase', vector, ptr2);
vector = calllib('LibName', 'buildClassifierVectorBase', vector, ptr3);
Теперь я могу вызвать свой метод doSomethingWithPtrArray
:
ptr = calllib('LibName', 'doSomethingWithPtrArray', vector);
Это решение работает, но не самое приятное...