Pass C++ Structures to MATLAB Functions
R2026bThis example shows how to pass custom C++ structures directly to a MATLAB® function from a C++ engine application without manually converting the structure fields. In this example, you perform the following steps:
Create custom structures in a C++ header file.
Build a MATLAB interface to the structures.
Pass the structures to a MATLAB function.
Call this MATLAB function from your C++ application.
Build and run the C++ application.
This example uses in-process C++ libraries through the clib
interface. Passing C++ structures to MATLAB functions using out-of-process C++ libraries is not supported.
Prerequisites
Before you begin, complete these prerequisite tasks:
Verify that you have met all of the requirements to build a C++ program using the MATLAB Engine API for C++. For details, see Requirements to Build C++ Engine Applications.
Verify that you have set up a C++ development environment. For details, see Set Up C++ Development Environment.
Create a new work folder that is visible to the MATLAB search path. This example uses a folder named
C:\cpp\work.
Define Structures in C++ Header File
Create a C++ header file that defines the structures you want to pass to
MATLAB. This example defines Position and
Rectangle structures in a Shapes
namespace. Save the structure definitions in a file named
shapes.hpp.
shapes.hpp |
|---|
|
Build MATLAB Interface to Structures
Build a MATLAB interface to the structures you defined. Before building the interface, select the C++ compiler you want to use by running this command:
mex -setup C++
To build the interface, use a clibgen.api.InterfaceDefinition object. (since R2026b)
For this example, the code creates a folder named ShapesLib and
builds the interface, ShapesLibInterface.dll, in this folder. The
Position and Rectangle structures in C++
map to clib.ShapesLib.Shapes.Position and
clib.ShapesLib.Shapes.Rectangle objects in MATLAB.
icfg = clibgen.api.InterfaceConfiguration("ShapesLib",HeaderFiles="shapes.hpp",IncludePath=pwd); idef = clibgen.api.InterfaceDefinition(icfg); idef.build;
Before R2026b: Build the interface using the
clibgen.buildInterface
function.
clibgen.buildInterface("shapes.hpp",InterfaceName="ShapesLib")
Add the interface folder to the MATLAB search path so that you can use the generated clib
objects in MATLAB.
addpath("C:\cpp\work\ShapesLib")Pass Structures to MATLAB Function Using Interface
You can pass C++ structures to MATLAB functions by using the interface you built. For example, create a
MATLAB function, createRectangle, that uses the
ShapesLib interface to create a Rectangle
structure from two input Position structures. Save the function
in a file named createRectangle.m.
createRectangle.m |
|---|
function rect = createRectangle(pt1,pt2) %CREATERECTANGLE - Create rectangle using MATLAB interface to C++ arguments (Input) pt1 (1,1) clib.ShapesLib.Shapes.Position pt2 (1,1) clib.ShapesLib.Shapes.Position end arguments (Output) rect (1,1) clib.ShapesLib.Shapes.Rectangle end rect = clib.ShapesLib.Shapes.Rectangle(); rect.UpperLeft = pt1; rect.LowerRight = pt2; end |
The arguments blocks in this function validate the
clib input and output structures. These blocks are optional
but enable autocompletion for the structures in the MATLAB Editor. These type validations also enable your C++ application to
internally pass the structures by reference instead of copying them field by field
from MATLAB to C++.
Call MATLAB Function from C++ Application
You can call MATLAB functions that use C++ structures from your C++ application. For
example, write a C++ application, myMain.cpp, that creates a
rectangle using the MATLAB function and the structures defined in the header file.
The
includestatements provide access to the MATLAB Engine header file and the header file that contains the structures.The
USING_TYPE_WITH_MATLABmacros associate each structure with the interface library name. These macros must appear at file scope, outside of any function.MATLAB starts in the same process that executes your C++ code (
IN_PROCESSmode).The
addpathcommands add the path to the folder containing your C++ code and theShapesLiblibrary so that they are available at run time. Update the paths shown in the application to use the paths for your platform. To avoid including these commands in your code, add the equivalent MATLABaddpathcommands to yourstartup.mfile. For more details on MATLAB startup files, see Startup Options in MATLAB Startup File.The
fevalfunction calls thecreateRectangleMATLAB function, accepting pointers to twoPositionstructures as input and returning a pointer to theRectanglestructure. When usingfevalwith structures, you must specify pointers to input and output structures.The application deallocates the memory referenced by the rectangle pointer before exiting. When
fevalreturns a structure pointer, the C++ application takes ownership of the allocated memory. When you no longer need the rectangle pointer, usedeleteon the pointer to deallocate the memory it references.
This application runs on Windows® or Linux®. Running this application on Mac requires changes to the application logic. For more details, see the Run Application on Mac Platforms section.
myMain.cpp |
|---|
|
Build and Run Application
Build and run the C++ application. Before building the application, select the C++ compiler you want to use. You must select the same compiler you used earlier to build the MATLAB interface to the structures. At the MATLAB command prompt, run this command:
mex -setup -client engine C++
Build an executable file for the application. The compiler creates the executable
named myMain in the same folder as your code.
mex -client engine myMain.cpp
From the operating system command line, run the application. To run this application, your run-time environment must be configured to find MATLAB libraries, as described in Requirements to Build C++ Engine Applications.
.\myMainUpper left: (0, 0) Lower right: (10, 5)
The application displays the rectangle points. To modify the application, update
your myMain.cpp file, and then rebuild the executable and rerun
it.
Application Variations
You can customize the application to return a different number of outputs, call the MATLAB function asynchronously, or run on Mac platforms.
Return No Outputs or Multiple Outputs
In this example, the C++ application used feval to return
a single output from the MATLAB function. The syntax to return no outputs or multiple outputs is
slightly different.
If your MATLAB function returns no outputs, use
voidas the return value. For example, this code calls a MATLAB function,updatePosition, that modifies thePositionstructures of the rectangle in place, without returning a value.matlabPtr->feval<void>(u"updatePosition", &pt1, &pt2);If your MATLAB function returns multiple outputs, use
std::tupleas the return value. For example, this code calls a MATLAB function,getRectangleInfo, that returns the area of a rectangle as adoublevalue and the center of the rectangle as aPositionstructure.auto [area, center] = matlabPtr->feval<std::tuple<double, Shapes::Position*>>( u"getRectangleInfo", &pt1, &pt2);
Call MATLAB Function Asynchronously
To call the MATLAB function asynchronously, use fevalAsync
instead of feval. The fevalAsync
function returns a FutureResult object that you can use to
retrieve the output structure when the call completes. For example, this code
calls createRectangle asynchronously and retrieves the result
using
future.get().
FutureResult<Shapes::Rectangle*> future = matlabPtr->fevalAsync<Shapes::Rectangle*>(u"createRectangle", &pt1, &pt2);
// Do other work while MATLAB executes
Shapes::Rectangle* rectPtr = future.get();Run Application on Mac Platforms
On Mac platforms, in-process mode requires MATLAB to run on the main thread of the process. To start MATLAB on the main thread, use matlab::engine::runMacLoopInProcess. Place your application code in a
separate function and pass it to runMacLoopInProcess so that
the code runs in a secondary
thread.
int appCode(int argc, char *argv[]) {
using namespace matlab::engine;
std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB(MATLABApplicationMode::IN_PROCESS);
// Application code here
return 0;
}
int main(int argc, char *argv[]) {
return matlab::engine::runMacLoopInProcess(appCode, argc, argv);
}