Main Content

MATLAB Objects in MEX Functions

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:

  • Handle objects - Changes made to handle objects in MEX functions affect the object in the caller's workspace.

  • Value objects - Changes made to value objects in MEX functions affect only the independent copy of the object in the workspace of the MEX 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 a matlab::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, call getProperty 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 a matlab::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 the matlabPtr 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, call setProperty with index of the object in the array whose property value you want to set. For example, this code snippet sets the value of the Name 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. The Picture 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 the EmployeeID class to reduce the intensity of the brightest values in the image. The MEX function performs these steps:

  • Moves the input argument to a matlab::data::Array using std::move.

  • Uses getProperty to get the value of the property to modify.

  • Defines the variable as a type appropriate for the property value. Use matlab::data::TypedArray<uint8_t> because the MATLAB type is uint8.

  • Reassign the modified array to the object property using setProperty.

  • Returns the modified object as the MEX function output.

#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.

  • Argument checking confirms the correct number of inputs and calls the MATLAB isa to determine the class of the input object.

  • Support for either char or string input for value to set Name property.

  • Comparison of current property value to determine if the update needs to be made.

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:

  • The MEX function must be called with two arguments.

  • The first argument must be an object of the EmployeeID class.

    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 MATLAB char vector or as a string and assigns the input defined as a matlab::data::CharArray or a matlab::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

|

Related Topics