MATLAB Objects in MEX Functions - MATLAB & Simulink (original) (raw)

MEX functions can access MATLABĀ® object properties using the setProperty and getProperty member functions. Objects passed to MEX functions behave like objects passed to any MATLAB function:

Therefore, value objects modified in MEX functions must be returned to the caller, whereas handle objects do not need to be returned. For more information on object behavior, see Object Modification.

Get Property Value

To get a property value, make a shared copy of the object as amatlab::data::Array. For example, assuming the object is the first input argument, assign it to a variable:

matlab::data::Array object(inputs[0]);

Create a MATLAB data array of the correct type for the property value. For example, assuming a property called Name contains a MATLAB character vector, define the new value as a matlab::data::CharArray. Use the matlab::data::ArrayFactory to create the array.

matlab::data::CharArray propName = matlabPtr->getProperty(object, u"Name");

Get Property Value from Object Array

If the input to the MEX function is an object array, callgetProperty with index of the object in the array whose property value you want to get. For example, this code snippet returns the value of the Name property for the fourth element in the object array,objectArray.

matlab::data::Array objectArray(inputs[0]);
matlab::data::CharArray propName = matlabPtr->getProperty(objectArray, 3, u"Name");

Set Property Value

To set a property value, make a shared copy of the object as amatlab::data::Array. For example, assuming the object is the first input argument, assign it to a variable.

matlab::data::Array object(inputs[0]);

Create a MATLAB data array of the correct type for the property value. For example, assuming a property called Name contains a MATLAB character vector, define the new value as a matlab::data::CharArray. Use the matlab::data::ArrayFactory to create the array.

Call the MATLAB engine setProperty function with thematlabPtr shared pointer.

matlabPtr->setProperty(object, u"Name",
    factory.createCharArray("New value for Name"));

Set Property Value in Object Array

If the input to the MEX function is an object array, callsetProperty with index of the object in the array whose property value you want to set. For example, this code snippet sets the value of theName property for the fourth element in the object array,objectArray.

matlab::data::Array objectArray(inputs[0]);
matlabPtr->setProperty(objectArray, 3, u"Name",   
    factory.createCharArray("New value for Name"));

Object Property Copy-On-Write Behavior

When a MEX function modifies an object property by assigning a value to the property, the property value is no longer shared with the object in the caller's workspace. The data in properties that are not modified remain shared. That is, copy-on-write behavior affects the modified property, not the entire object.

Modify Property and Return Object

This example uses the EmployeeID class to create an object. This class defines two properties. The Name property is defined as a 1-by-any number of elements array of type char. ThePicture property is defined as a 1000-by-800 element array of type uint8 for the employee image.

classdef EmployeeID properties Name (1,:) char Picture (1000,800) uint8 end methods function obj = EmployeeID(n,p) if nargin > 0 obj.Name = n; obj.Picture = p; end end end end

The following MEX function modifies the image contained in an object of theEmployeeID class to reduce the intensity of the brightest values in the image. The MEX function performs these steps:

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

using matlab::mex::ArgumentList;
using namespace matlab::data;

class MexFunction : public matlab::mex::Function {
    std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
public:
    void operator()(ArgumentList outputs, ArgumentList inputs) {

        // Move object to variable
        Array obj = std::move(inputs[0]);

        // Get property value and modify
        TypedArray<uint8_t> imageData = matlabPtr->getProperty(obj, u"Picture");
        for (auto& elem : imageData) {
            if (elem > 240) {
                elem = elem - elem/100;
            }
        }

        // Set property value and assign to output
        matlabPtr->setProperty(obj, u"Picture", imageData);
        outputs[0] = obj;
    }
};

After saving this code in a file (called reduceGlare.cpp in this example), compile it with the mex function. Call this MEX function from MATLAB with an EmployeeID object as input.

EmployeeObject = EmployeeID('My Name',randi([1 255],1000,800,'uint8')); EmployeeObject = reduceGlare(EmployeeObject);

Only Modified Property Causes Copy

This example creates a MEX function that accepts a EmployeeID object and a new value for its Name property as its inputs. After setting the property to the new value, the function returns the modified object. This MEX function performs some additional steps that can be useful in your program.

To see the source code, click modifyObjectProperty.cpp and EmployeeID.m to open the files in the MATLAB Editor. Use the mex command to build the MEX function.

To run this example, add the modifyObjectProperty.cpp file and the EmployeeID.m class to a folder on your MATLAB path. After performing the mex setup, execute these statements:

mex modifyObjectProperty.cpp EmployeeObject = EmployeeID('My Name',randi([1 255],1000,800,'uint8')); EmployeeObject = modifyObjectProperty(EmployeeObject,'New Name');

Here is the MexFunction::operator() implementation.

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

using matlab::mex::ArgumentList;
using namespace matlab::data;

class MexFunction : public matlab::mex::Function {
public:
    void operator()(ArgumentList outputs, ArgumentList inputs) {
        // Check for correct inputs
        checkArguments(outputs, inputs);

        // Assign the input object to a matlab::data::Array
        Array object(inputs[0]);

        // Member function to set properyt value
        assignProperty(object, inputs);

        // Return modified object
        outputs[0] = object;
    }

The MexFunction::checkArguments function performs these checks:

    void checkArguments(ArgumentList out, ArgumentList in) {
        std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
        ArrayFactory factory;

        // Check number of inputs
        if (in.size() != 2) {
            matlabPtr->feval(u"error", 0,
                std::vector<Array>({ factory.createScalar("Two inputs required") }));
        }
        // Use isa function to test for correct class
        std::vector<Array> args{ in[0], factory.createCharArray("EmployeeID") };
        TypedArray<bool> result = matlabPtr->feval(u"isa", args);
        if (result[0] != true) {
            matlabPtr->feval(u"error", 0, 
               std::vector<Array>({ factory.createScalar("Input must be EmployeeID object") }));
        }     
    }

The MexFunction::assignProperty function determines if the new value for the property is passed in as a MATLABchar vector or as a string and assigns the input defined as amatlab::data::CharArray or amatlab::data::StringArray respectively.

Before assigning the new value to the Name property, this function compares the current value to determine if it is different and avoids making an assignment if it is not.

    void assignProperty(Array& obj, ArgumentList in) {
        std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
        ArrayFactory factory;
        std::string newPropertyValue;

        // Determine if input is MATLAB char or MATLAB string
        if (in[1].getType() == ArrayType::CHAR) {
            CharArray newName(in[1]);
            newPropertyValue = newName.toAscii();
        }
        else if (in[1].getType() == ArrayType::MATLAB_STRING) {
            StringArray newName(in[1]);
            newPropertyValue = (std::string)newName[0];
        }
        else {
            matlabPtr->feval(u"error", 0,
                std::vector<Array>({ factory.createScalar("Name must be char or string") }));
        }

        // If new value is different from new value, set new value
        CharArray currentName = matlabPtr->getProperty(obj, u"Name");
        if (currentName.toAscii() != newPropertyValue) {
            matlabPtr->setProperty(obj, u"Name", factory.createCharArray(newPropertyValue));
        }
    }

Handle Objects

For an example that uses a handle object, download the following file and follow the instructions in the file to build and run the MEX function.

mexgetproperty.cpp

See Also

setProperty | getProperty

Topics