Вот то, как создать основную MEX-функцию C++. Эта функция просто добавляет смещение к каждому элементу входного массива, чтобы продемонстрировать основной ввод и вывод. Для более детального обсуждения создания исходного кода MEX-функции смотрите Структуру MEX-функции C++ и похожих тем.
Используя ваш редактор, создайте файл с расширением .cpp
и добавьте, прокомментировали инструкции. Например, MyMEXFunction.cpp
.
/* MyMEXFunction * Adds second input to each * element of first input * a = MyMEXFunction(a,b); */
Для MEX-функций C++ добавьте эти заголовочные файлы
/* MyMEXFunction * Adds second input to each * element of first input * a = MyMEXFunction(a,b); */ #include "mex.hpp" #include "mexAdapter.hpp"
Опционально задайте пространство имен для matlab::data
и задайте другие удобства.
/* MyMEXFunction * Adds second input to each * element of first input * a = MyMEXFunction(a,b); */ #include "mex.hpp" #include "mexAdapter.hpp" using namespace matlab::data; using matlab::mex::ArgumentList;
Все MEX-функции C++ реализованы как класс под названием MexFunction
. Этот класс должен вывести от matlab::mex::Function
.
/* MyMEXFunction * Adds second input to each * element of first input * a = MyMEXFunction(a,b); */ #include "mex.hpp" #include "mexAdapter.hpp" using namespace matlab::data; using matlab::mex::ArgumentList; class MexFunction : public matlab::mex::Function { };
Все классы MexFunction
должны заменить оператор вызова функции, operator()
, чтобы принять два аргумента типа matlab::mex::ArgumentList
. Эти аргументы содержат вводы и выводы.
/* MyMEXFunction * Adds second input to each * element of first input * a = MyMEXFunction(a,b); */ #include "mex.hpp" #include "mexAdapter.hpp" using namespace matlab::data; using matlab::mex::ArgumentList; class MexFunction : public matlab::mex::Function { public: void operator()(ArgumentList outputs, ArgumentList inputs) { } };
Протестируйте, чтобы видеть, имеют ли аргументы правильный тип и размер. Если тесты приводят к сбою, вызывают
функцию MATLAB® error
.
/* MyMEXFunction * Adds second input to each * element of first input * a = MyMEXFunction(a,b); */ #include "mex.hpp" #include "mexAdapter.hpp" using namespace matlab::data; using matlab::mex::ArgumentList; class MexFunction : public matlab::mex::Function { public: void operator()(ArgumentList outputs, ArgumentList inputs) { } void checkArguments(ArgumentList outputs, ArgumentList inputs) { // Get pointer to engine std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine(); // Get array factory ArrayFactory factory; // Check first input argument if (inputs[0].getType() != ArrayType::DOUBLE || inputs[0].getType() == ArrayType::COMPLEX_DOUBLE || inputs[0].getNumberOfElements() != 1) { matlabPtr->feval(u"error", 0, std::vector<Array>({ factory.createScalar("First input must scalar double") })); } // Check second input argument if (inputs[1].getType() != ArrayType::DOUBLE || inputs[1].getType() == ArrayType::COMPLEX_DOUBLE) { matlabPtr->feval(u"error", 0, std::vector<Array>({ factory.createScalar("Input must double array") })); } // Check number of outputs if (outputs.size() > 1) { matlabPtr->feval(u"error", 0, std::vector<Array>({ factory.createScalar("Only one output is returned") })); } } };
Получите скалярное смещение и присвойте его
double
const
. Получите входной массив и переместите его в matlab::data::TypedArray<double>
, чтобы работать на массиве. Добавьте смещение к каждому элементу в массиве и присвойте измененный массив выходной переменной.
/* MyMEXFunction * Adds second input to each * element of first input * a = MyMEXFunction(a,b); */ #include "mex.hpp" #include "mexAdapter.hpp" using namespace matlab::data; using matlab::mex::ArgumentList; class MexFunction : public matlab::mex::Function { public: void operator()(ArgumentList outputs, ArgumentList inputs) { checkArguments(outputs, inputs); const double offSet = inputs[0][0]; TypedArray<double> doubleArray = std::move(inputs[1]); for (auto& elem : doubleArray) { elem += offSet; } outputs[0] = doubleArray; } void checkArguments(ArgumentList outputs, ArgumentList inputs) { // Get pointer to engine std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine(); // Get array factory ArrayFactory factory; // Check first input argument if (inputs[0].getType() != ArrayType::DOUBLE || inputs[0].getType() == ArrayType::COMPLEX_DOUBLE || inputs[0].getNumberOfElements() != 1) { matlabPtr->feval(u"error", 0, std::vector<Array>({ factory.createScalar("First input must scalar double") })); } // Check second input argument if (inputs[1].getType() != ArrayType::DOUBLE || inputs[1].getType() == ArrayType::COMPLEX_DOUBLE) { matlabPtr->feval(u"error", 0, std::vector<Array>({ factory.createScalar("Input must double array") })); } // Check number of outputs if (outputs.size() > 1) { matlabPtr->feval(u"error", 0, std::vector<Array>({ factory.createScalar("Only one output is returned") })); } } };
После установки поддерживаемого компилятора используйте команду mex
, чтобы создать вашу MEX-функцию.
mex -setup c++ mex MyMEXFunction.cpp
Для получения дополнительной информации о создании MEX-функций смотрите Сборку Программы C++ MEX.
Вызовите свою MEX-функцию от MATLAB.
b = MyMEXFunction(11.5, rand(1000));
mATLAB:: mEX:: ArgumentList
| mATLAB:: mEX:: Функция
| mEX