Вот то, как создать основную 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::Function | mex