Create a C++ MEX Source File

Here is how to create a basic C++ MEX function. This function just adds an offset to each element of an input array to demonstrate basic input and output. For a more detailed discussion on creating MEX function source code, see Structure of C++ MEX Function and related topics.

Create Source File

Using your editor, create a file with a .cpp extension and add commented instructions. For example, MyMEXFunction.cpp.

/* MyMEXFunction
 * Adds second input to each  
 * element of first input
 * a = MyMEXFunction(a,b);
*/

Add Required Header Files

For C++ MEX functions, add these header files.

/* MyMEXFunction
 * Adds second input to each  
 * element of first input
 * a = MyMEXFunction(a,b);
*/

#include "mex.hpp"
#include "mexAdapter.hpp"

Using Convenience Definitions

Optionally specify the namespace for matlab::data and define other conveniences.

/* 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;

Define MexFunction Class

All C++ MEX functions are implemented as a class named MexFunction. This class must derive from 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 {

};

Define operator()

All MexFunction classes must override the function call operator, operator(), to accept two arguments of type matlab::mex::ArgumentList. These arguments contain the inputs and outputs.

/* 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) {

    }

};

Add Member Function to Check Arguments

Test to see if the arguments are of the correct type and size. If tests fail, call the MATLAB® error 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 {
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 be 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 be 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") }));
        }
    }
};

Implement Computation

Get the scalar offset and assign it to a const double. Get the input array and move it to a matlab::data::TypedArray<double> to work on the array. Add the offset to each element in the array and assign the modified array to the output variable.

/* 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 be 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 be 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") }));
        }
    }
};

Setup and Build

After installing a supported compiler, use the mex command to build your MEX function.

mex -setup c++
mex MyMEXFunction.cpp

For more information on building MEX functions, see Build C++ MEX Programs.

Call MEX Function

Call your MEX function from MATLAB.

b = MyMEXFunction(11.5, rand(1000));

See Also

| |

Related Topics