Проблемы с вызовом кода C ++ из MATLAB 2016 с использованием вспомогательного файла C с MEX Wrapper - PullRequest
0 голосов
/ 30 мая 2019

Мне нужно вызвать функцию, не являющуюся членом C ++, из MATLAB 2016. MATLAB не поддерживал C ++ MEX до 2018 года, поэтому возникает проблема.

Я делаю это в Windows под mingw64.

Чтобы обойти это, я попытался создать файл C с помощью оболочки MEX, при этом реализация C просто вызывала функцию C ++, используя общий заголовочный файл с extern "C", на основе некоторых советов в Интернете.

Однако я очень новичок в MATLAB, вызывая C ++ из C и некоторые другие понятия здесь.Так что ничего не компилируется должным образом.

Любые советы по правильному подходу к этому очень приветствуются.

Заголовочный файл myFunc.h:

#ifndef CPP_H
#define CPP_H

#ifdef __cplusplus
void myFunc(const std::vector<myStruct>& a,
            const std::vector<myStruct>& b,
            const double c,
            std::vector<std::pair>& d,
            mxArray **e
            );
extern "C" {
#endif
void myFunc(const std::vector<myStruct>& a,
            const std::vector<myStruct>& b,
            const double c,
            std::vector<std::pair>& d,
            mxArray **e
            );
#ifdef __cplusplus
}
#endif

#endif

Файл C для его вызова, myFuncCaller.c:

#include "myFunc.h"
#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    myFunc(prhs[0], prhs[1], prhs[2], prhs[3], prhs[4]);
}

Фактическая реализация: myFunc.cpp:

#include "myFunc.h"

void myFunc(const std::vector<myStruct>& a,
            const std::vector<myStruct>& b,
            const double c,
            std::vector<std::pair>& d,
            mxArray **e
            )
{
  //things done here, pushes results to d
}

Конечным результатом попытки скомпилировать оба из них является то, что:

  • файл C не видит mex.h (не знаю, почему, поскольку MATLAB утверждает, что mingwэто жалоба)
  • заголовочный файл, скорее всего, неверен и утверждает, что "type по умолчанию int в объявлении std".Я предполагаю, что это потому, что у меня есть некоторые связанные с C ++ вещи в разделе C.Я не уверен, как подойти к этому.
  • Файл C ++ жалуется больше всего.Я мог бы опубликовать все ошибки, но я не думаю, что это будет продуктивно, учитывая, что в моей логике, вероятно, есть фундаментальный недостаток.

Одним из больших препятствий является подход передачи входных аргументов из MATLAB -> C -> C ++.Я не хочу, чтобы вещи были «потеряны», и в идеале не хочу делать конвертацию без необходимости, и я не уверен, где это будет.

1 Ответ

1 голос
/ 31 мая 2019
  1. Вы не можете поместить std::vector<> в раздел extern "C", так как это недопустимый синтаксис языка C. Вам необходимо создать чистую заглушку функции C, скомпилированную как C ++, которая вызывает функцию C ++.

  2. Но вам не нужно ничего этого делать, потому что вы можете прекрасно скомпилировать MEX-файл C ++. API - это C, но вы можете без проблем вызывать C-функции из C ++.

  3. Фактическая проблема в mexFunction состоит в том, что вы передаете указатели на mxArray объекты, где функция ожидает ссылки на std::vector<> и т. Д. Единственный способ сделать это право - скопировать данные из MATLAB массив в вектор C ++:

#include "myFunc.h"
#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
   if (nrhs < 5) {
      mexErrMsgTxt("Not enough input arguments! 5 expected.");
   }

   // arg 1: std::vector<myStruct>
   if (!mxIsDouble(prhs[0])) {
      mexErrMsgTxt("First input argument must be a double array.");
   }
   std::size_t N = mxGetNumberOfElements(prhs[0]);
   double* pr = mxGetPr(prhs[0]);
   std::vector<myStruct> a(N);
   std::copy(pr, pr+N, a.begin());

   // arg 2: std::vector<myStruct>
   std::vector<myStruct> b; 
   // ...

   // arg 3: double
   double c = mxGetScalar(prhs[2]);

   // arg 4: std::vector<std::pair> // This makes no sense in C++, std::pair<> is a template, 2 template arguments missing!!
   std::vector<std::pair> d;
   // ...

   // arg 5: mxArray **  // is this the output? Why does your C++ function take an mxArray?

   myFunc(a, b, c, d, &prhs[4]);
}
...