MEX functions can access MATLAB® object properties using the matlab::engine::MATLABEngine::setProperty and matlab::engine::MATLABEngine::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.
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");
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");
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"));
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"));
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.
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 matlab::engine::MATLABEngine::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 matlab::engine::MATLABEngine::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);
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)); } }
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.
matlab::engine::MATLABEngine::getProperty | matlab::engine::MATLABEngine::setProperty