If your shared library contains data types or language features not supported by the MATLAB® interface to C++ libraries, you might be able to include this functionality by creating a wrapper header file. This topic provides examples for some limitations. For more information, see Limitations to C/C++ Support.
To run the workaround examples on Windows®:
Copy the C++ header file statements into .hpp
files.
Copy the source code into .cpp
files and build, using
instructions in Build Example Shared Library Files on Windows.
Execute the MATLAB code to build the interface.
If required, edit the library definition file.
Execute the MATLAB code to test the functionality.
std
NamespaceA MATLAB interface to a C++ library does not include functions that use objects
defined in the std
namespace. For example, the functions in this
Student.hpp
header file pass std::stack
objects. If you build the MATLAB interface, functions readStudents
and
getStudents
are not included.
#ifndef STUDENT_HEADER #define STUDENT_HEADER #include <stack> #ifdef _WIN32 #ifdef EXPORT #define DLL_EXPORT __declspec(dllexport) #else #define DLL_EXPORT __declspec(dllimport) #endif #else #define DLL_EXPORT __attribute__((visibility ("default"))) #endif class DLL_EXPORT Student { int rollNumber; public: Student(); Student(int rollNo); int getRollNumber(); }; DLL_EXPORT void readStudents(const std::stack<Student>& students); DLL_EXPORT std::stack<Student> getStudents(int size); #endif
To run this example on Windows, create the Student.lib
and
Student.dll
files from this
Student.cpp
source file, using Build Example Shared Library Files on Windows.
#define EXPORT #include "Student.hpp" Student::Student() : rollNumber(0) {} Student::Student(int rollNo) : rollNumber(rollNo) {} int Student::getRollNumber() { return rollNumber; } DLL_EXPORT void readStudents(const std::stack<Student>& students) { } DLL_EXPORT std::stack<Student> getStudents(int size) { std::stack<Student> students; for (int i = 0; i < size; i++) { students.push(Student(i+1)); } return students; }
Create the Student.hpp
header file and put it with the
Student.dll
shared library file in a folder identified as
rtpath
.
Create a class CStack
to represent an
std::stack
object. Put this definition in a header file
CStack.hpp
.
//Wrapper header to access/pass std::stack objects from MATLAB #ifndef stack_header #define stack_header #include <stack> #include <stdexcept> template<typename T> class CStack { std::stack<T> data; public: CStack() {} // This parameterized constructor is required for the wrapper functions // and is not included in the MATLAB interface CStack(const std::stack<T>& d):data(d) {} // Function to access the topmost element in stack T* get() { if (data.empty()) throw std::runtime_error("Retrieving element from Empty Stack"); return &data.top(); } // Function to remove elements from stack void remove() { if (data.empty()) throw std::runtime_error("Stack is empty"); data.pop(); } // Function to add elements to stack void add(const T* element) { data.push(*element); } // This method is required for the wrapper functions, and // is not included in the MATLAB interface const std::stack<T>& getData() const{ return data; } }; #endif
Define a function readStudentsWrapper
to call the
readStudents
function using the CStack
class and getStudentsWrapper
to call the
getStudents
function. Include these functions in a
wrapper header file named StudentWrapper.hpp
.
//Header to call readStudents and getStudents functions from MATLAB #include "Student.hpp" #include "CStack.hpp" //wrapper function to access the function that accepts std::stack input void readStudentsWrapper(const CStack<Student>& students) { readStudents(students.getData()); } //wrapper function to access the function that returns the std::stack CStack<Student> getStudentsWrapper(int size) { auto students = getStudents(size); CStack<Student> cstackStudents(students); return cstackStudents; }
Generate a library definition in a package named
stack
.
clibgen.generateLibraryDefinition(["Student.hpp","StudentWrapper.hpp"],"PackageName","stack",... "Libraries","Student.lib","TreatObjectPointerAsScalar",true,"Verbose",true);
Warning: File 'manifest.json' not found. Warning: Some C++ language constructs in the header file are not supported and not imported. Did not add 'readStudents' at Student.hpp:24. Type 'stack' is from std namespace or system header and is not supported. Did not add 'getStudents' at Student.hpp:26. Type 'stack' is from std namespace or system header and is not supported. Did not add constructor to class 'CStack<Student>' at CStack.hpp:16. Type 'stack' is from std namespace or system header and is not supported. Did not add member 'getData' to class 'CStack<Student>' at CStack.hpp:39. Type 'stack' is from std namespace or system header and is not supported. Using MinGW64 Compiler (C++) compiler. Generated definition file definestack.mlx and data file 'stackData.xml' contain definitions for 13 constructs supported by MATLAB. Build using build(definestack).
Ignore the Did not add
messages. In MATLAB, you call functions readStudentsWrapper
and
getStudentsWrapper
instead of
readStudents
and getStudents
. The
constructor to class CStack
and member
getData
are used internally and are not callable from the
interface.
Build the interface.
build(definestack)
addpath('stack')
Add the shared library path to the system (run-time) path. If the file is
located on rtPath
, then type:
syspath = getenv('PATH'); rtPath = 'myrtpathname'; setenv('PATH',[rtPath ';' syspath]);
Call readStudentsWrapper
.
studentsStack = clib.stack.CStack_Student_; studentsStack.add(clib.stack.Student(1)) studentsStack.add(clib.stack.Student(2)) studentsStack.add(clib.stack.Student(3)) clib.stack.readStudentsWrapper(studentsStack)
Call getStudentsWrapper
.
clear studentsStack; studentsStack = clib.stack.getStudentsWrapper(3); student = studentsStack.get; % returns topmost element from studentStack studentsStack.remove % removes topmost element of stack
A MATLAB interface to a C++ library does not support uninstantiated template
classes. For example, the class Pairs
in this
Templates.hpp
header file is not instantiated.
// Header for Template class #ifndef templates_Header #define templates_Header template <class T> class Pairs { public: T val1; T val2; Pairs() : val1(0), val2(0) {} Pairs(T first, T second) : val1(first), val2(second) {} T getVal1() { return val1; } T getVal2() { return val2; } }; #endif
To include the Pairs
class, create this wrapper header file
TemplatesWrapper.hpp
. Assume that
Pairs
supports int
and
double
data types.
//Wrapper to instantiate template class Pairs #include "Templates.hpp" /* Data types that will be used for Pairs class. */ template class Pairs<int>; template class Pairs<double>;
Generate the library definition.
clibgen.generateLibraryDefinition(["TemplatesWrapper.hpp","Templates.hpp"],"PackageName","Templates","Verbose",true)
Generated definition file defineTemplates.mlx and data file 'TemplatesData.xml' contain definitions for 16 constructs supported by MATLAB. Build using build(defineTemplates).
Build the interface.
build(defineTemplates)
addpath('Templates')
Create Pairs
objects and call the
getVal1
and getVal2
functions.
Pairs1 = clib.Templates.Pairs_int_(2,3); Val1 = Pairs1.getVal1; Pairs2 = clib.Templates.Pairs_double_(4.5,10.9); Val2 = Pairs2.getVal2; Pairs3 = clib.Templates.Pairs_int_(4.3,10.9); Val2 = Pairs3.getVal2;
A MATLAB interface to a C++ library does not include functions with void
*
arguments or return types. For example, if you build a MATLAB interface to this ContentHidden.hpp
header file, the
getObjWithContentHidden
and
sizeOfObjWithContentHidden
functions are not included.
//Header file with void* as argument/return type for function #ifndef CONTENT_HIDDEN #define CONTENT_HIDDEN #include <vector> #ifdef _WIN32 #ifdef EXPORT #define DLL_EXPORT __declspec(dllexport) #else #define DLL_EXPORT __declspec(dllimport) #endif #else #define DLL_EXPORT __attribute__((visibility ("default"))) #endif DLL_EXPORT void* getObjWithContentHidden(); //function with return type as void pointer gets dropped in MATLAB C++ Interface DLL_EXPORT unsigned int sizeOfObjWithContentHidden(void* pobj); //function with argument as void pointer gets dropped in MATLAB C++ Interface #endif
To run this example on Windows, create the
ContentHidden.lib
and
ContentHidden.dll
files from this
ContentHidden.cpp
source file, using Build Example Shared Library Files on Windows.
#define EXPORT #include "ContentHidden.hpp" DLL_EXPORT void* getObjWithContentHidden() { std::vector<int> *vecData = new std::vector<int>({1,2,3,4}); return vecData; } DLL_EXPORT unsigned int sizeOfObjWithContentHidden(void* pobj) { return (static_cast<std::vector<int> *> (pobj))->size(); }
Create the ContentHidden.hpp
header file and put it with
the ContentHidden.dll
shared library file in a folder
identified as rtpath
.
Define a function getObjWrapper
to call the
getObjWithContentHidden
function and
sizeOfObjWrapper
to call the
sizeOfObjWithContentHidden
function. Include these
functions in a wrapper header file named
VoidPointerWrapper.hpp
.
//Wrapper to access function with void* as argument/return type #pragma once #include "ContentHidden.hpp" class VoidType {}; //wrapper class to convert void* to VoidType* VoidType* getObjWrapper() { return static_cast<VoidType*> (getObjWithContentHidden()); } unsigned int sizeOfObjWrapper(VoidType* pobj) { return sizeOfObjWithContentHidden(pobj); }
Generate a library definition in a package named
VoidPointer
.
clibgen.generateLibraryDefinition(["ContentHidden.hpp","VoidPointerWrapper.hpp"],"PackageName","VoidPointer",... "Libraries","ContentHidden.lib","TreatObjectPointerAsScalar",true,"Verbose",true)
Warning: Some C++ language constructs in the header file are not supported and not imported. Did not add 'getObjWithContentHidden' at ContentHidden.hpp:17. 'void *' is not a supported type. Did not add 'sizeOfObjWithContentHidden' at ContentHidden.hpp:19. 'void *' is not a supported type. Using MinGW64 Compiler (C++) compiler. Generated definition file defineVoidPointer.mlx and data file 'VoidPointerData.xml' contain definitions for 5 constructs supported by MATLAB. Build using build(defineVoidPointer).
Ignore the Did not add
messages. In MATLAB, you call functions getObjWrapper
and
sizeOfObjWrapper
instead of getObj
and
sizeOfObj
..
Build the interface.
build(defineVoidPointer)
addpath('VoidPointer')
Display the contents of the interface.
summary(defineVoidPointer)
MATLAB Interface to VoidPointer Library Class clib.VoidPointer.VoidType Constructors: clib.VoidPointer.VoidType() clib.VoidPointer.VoidType(clib.VoidPointer.VoidType) No Methods defined No Properties defined Functions clib.VoidPointer.VoidType clib.VoidPointer.getObjWrapper() uint32 clib.VoidPointer.sizeOfObjWrapper(clib.VoidPointer.VoidType)
Add the shared library path to the system (run-time) path. If the file is
located on rtPath
, then type:
syspath = getenv('PATH'); rtPath = 'myrtpathname'; setenv('PATH',[rtPath ';' syspath]);
Call the functions.
voidObj = clib.VoidPointer.getObjWrapper objSize = clib.VoidPointer.sizeOfObjWrapper(voidObj)
voidObj = VoidType with no properties. objSize = uint32 4
A MATLAB interface to a C++ library does not support function pointer input
arguments. For example, this CreateTrackbar.hpp
header file defines
CvTrackbarCallback
as a function pointer. If you build a
MATLAB interface, the cvCreateTrackbar
function is not
included because the argument on_change
is a function pointer
CvTrackbarCallback
type.
#ifndef trackbar_header #define trackbar_header #ifdef _WIN32 #ifdef EXPORT #define DLL_EXPORT __declspec(dllexport) #else #define DLL_EXPORT __declspec(dllimport) #endif #else #define DLL_EXPORT __attribute__((visibility ("default"))) #endif #include <cstddef> typedef void( *CvTrackbarCallback) (int pos, void *userdata); //Function "cvCreateTrackbar" gets dropped in MATLAB C++ Interface due to Function Pointer input argument DLL_EXPORT int cvCreateTrackbar(const char *trackbar_name, const char *window_name, int *value, int count, CvTrackbarCallback on_change); DLL_EXPORT void MatchingMethod( int, void* ); #endif
To run this example on Windows, create the
CreateTrackbar.lib
and
CreateTrackbar.dll
files from this
CreateTrackbar.cpp
source file, using Build Example Shared Library Files on Windows.
#define EXPORT #include "CreateTrackbar.hpp" #include <iostream> DLL_EXPORT int cvCreateTrackbar(const char *trackbar_name, const char *window_name, int *value, int count, CvTrackbarCallback on_change = NULL){ return count; } DLL_EXPORT void MatchingMethod(int, void*){ std::cout << "Invoked Function : MatchingMethod" << std::endl; }
Create the CreateTrackbar.hpp
header file and put it with
the CreateTrackbar.dll
shared library file in a folder
identified as rtpath
.
To include cvCreateTrackbar
, create this wrapper header
file WrapperTrackbar.hpp
which defines
wrapperTrackbar
to access the function that accepts
function pointer input.
// Wrapper Header to access function pointer CvTrackbarCallback #include "CreateTrackbar.hpp" using CvTrackbarCallback = void (*) (int , void *); class CvTrackbarCallbackWrapper { public: CvTrackbarCallback const on_change; CvTrackbarCallbackWrapper(CvTrackbarCallback fptr) : on_change(fptr) {} }; template<CvTrackbarCallback fptr> class CvTrackbarCallbackWrapperTempl : public CvTrackbarCallbackWrapper { public: CvTrackbarCallbackWrapperTempl() : CvTrackbarCallbackWrapper(fptr){} }; template class CvTrackbarCallbackWrapperTempl<MatchingMethod>; // Wrapper function to access the function that accepts function pointer input int wrapperTrackbar(const char *trackbar_name, const char *window_name, int *value, int count, CvTrackbarCallbackWrapper const &callbackWrapper) { return cvCreateTrackbar(trackbar_name, window_name, value, count, callbackWrapper.on_change); }
Generate the library definition.
clibgen.generateLibraryDefinition(["CreateTrackbar.hpp","WrapperTrackbar.hpp"],"PackageName","Trackbar",... "Libraries","CreateTrackbar.lib","TreatObjectPointerAsScalar",true,"Verbose",true)
Warning: Some C++ language constructs in the header file are not supported and not imported. Did not add member 'on_change' to class 'CvTrackbarCallbackWrapper' at WrapperTrackbar.hpp:8. 'CvTrackbarCallback' is an alias of type '*'. 'CvTrackbarCallback const' is not a supported type. Did not add constructor to class 'CvTrackbarCallbackWrapper' at WrapperTrackbar.hpp:9. 'CvTrackbarCallback' is an alias of type '*'. '*' is not a supported type. Did not add 'MatchingMethod' at CreateTrackbar.hpp:21. 'void *' is not a supported type. Did not add 'cvCreateTrackbar' at CreateTrackbar.hpp:19. 'CvTrackbarCallback' is an alias of type '*'. '*' is not a supported type. Using MinGW64 Compiler (C++) compiler. Generated definition file defineTrackbar.mlx and data file 'TrackbarData.xml' contain definitions for 7 constructs supported by MATLAB. 1 construct(s) require(s) additional definition. To include these construct(s) in the interface, edit the definitions in defineTrackbar.mlx. Build using build(defineTrackbar).
To include the missing definitions, edit defineTrackbar.mlx
and define the name arguments to wrapperTrackbar
as
null-terminated strings. The updated code for trackbar_name
is:
defineArgument(wrapperTrackbarDefinition, "trackbar_name", "string", "input", "nullTerminated");
The updated code for window_name
is:
defineArgument(wrapperTrackbarDefinition, "window_name", "string", "input", "nullTerminated");
Define value
as an int32
scalar. The
updated code is:
defineArgument(wrapperTrackbarDefinition, "value", 'int32', "input", 1);
Save the file and build the interface.
build(defineTrackbar)
addpath('Trackbar')
Add the shared library path to the system (run-time) path. If the file is
located on rtPath
, then type:
syspath = getenv('PATH'); rtPath = 'myrtpathname'; setenv('PATH',[rtPath ';' syspath]);
Call the functions.
% Create a function pointer object. matchingMethodObj = clib.Trackbar.CvTrackbarCallbackWrapperTempl_MatchingMethod_; trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED"; image_window = "Source Image"; match_method = 0; max_Trackbar = 5; % Use the wrapper function to call cvCreateTrackbar with a function pointer input val = clib.Trackbar.wrapperTrackbar(trackbar_label,image_window,match_method,max_Trackbar,matchingMethodObj)
A MATLAB interface to a C++ library does not support preprocessor directives
(macros). For example, this Area.hpp
header file defines the macro
PI
. If you build a MATLAB interface, PI
is not included.
//Header with Macro preprocessor directive #ifndef area_header #define area_header #ifdef _WIN32 #ifdef EXPORT #define DLL_EXPORT __declspec(dllexport) #else #define DLL_EXPORT __declspec(dllimport) #endif #else #define DLL_EXPORT __attribute__((visibility ("default"))) #endif #define PI 3.1415 DLL_EXPORT double getArea(int radius, double piVal); #endif
To run this example on Windows, create the Area.lib
and
Area.dll
files from this Area.cpp
source file, using Build Example Shared Library Files on Windows.
#define EXPORT #include "Area.hpp" DLL_EXPORT double getArea(int radius, double piVal) { return piVal*radius*radius; }
Create the Area.hpp
header file and put it with the
Area.dll
shared library file in a folder identified as
rtpath
.
To include PI
, create this wrapper header file
WrapperPI.hpp
which defines function
getPI
to get the value of the preprocessor
directive.
//Wrapper to access the preprocessor directive value #include "Area.hpp" double getPI(){ //Wrapper function retrieves the value of PI return PI; }
Generate the library definition.
clibgen.generateLibraryDefinition(["Area.hpp","WrapperPI.hpp"],"PackageName","Area",... "Libraries","Area.lib","TreatObjectPointerAsScalar",true,"Verbose",true)
Build the interface.
build(defineArea)
addpath('Area')
Add the shared library path to the system (run-time) path. If the file is
located on rtPath
, then type:
syspath = getenv('PATH'); rtPath = 'myrtpathname'; setenv('PATH',[rtPath ';' syspath]);
Call getArea
.
pi = clib.Area.getPI; area = clib.Area.getArea(2,pi)
area = 12.5660
A MATLAB interface to a C++ library does not include functions with arguments
std::string
for element type of vector. For example, the
readStringVector
and getStringVector
functions
in this StringVector.hpp
header file are not included when you build
a MATLAB interface.
//Header file which accepts and return the vector of std::string #ifndef stringVec_header #define stringVec_header #include <vector> #include <string> #ifdef _WIN32 #ifdef EXPORT #define DLL_EXPORT __declspec(dllexport) #else #define DLL_EXPORT __declspec(dllimport) #endif #else #define DLL_EXPORT __attribute__((visibility ("default"))) #endif DLL_EXPORT void readStringVector(const std::vector<std::string>& stringVector); //readStringVector function gets dropped as vector of std::string input is not supported in MATLAB C++ interface. DLL_EXPORT std::vector<std::string> getStringVector(int size); //getStringVector function gets dropped as return type of vector of std::string is not supported for MATLAB C++ Interface #endif
To run this example on Windows, create the StringVector.lib
and StringVector.dll
files from this
StringVector.cpp
source file, using Build Example Shared Library Files on Windows.
#define EXPORT #include "StringVector.hpp" DLL_EXPORT void readStringVector(const std::vector<std::string>& stringVector) { } DLL_EXPORT std::vector<std::string> getStringVector(int size) { std::vector<std::string> stringVector; for (int i = 0; i < size; i++) { stringVector.push_back(("string"+ std::to_string(i+1))); } return stringVector; }
Create the StringVector.hpp
header file and put it with the
StringVector.dll
shared library file in a folder
identified as rtpath
.
To support std::vector
of type
std::string
, create a CVector
class,
which defines these methods to pass the std::vector
between
MATLAB and the library.
Parameterized constructor:
CVector(const std::vector<T>& d): data(d)
Move constructor:
CVector(std::vector<T>&& d) : data(std::move(d))
Method to access the element at an index:
T get(int index)
Method to add elements to vectors:
void add(const T& element)
Method to get data from vectors:
const std::vector<T>& getData() const
CVector.hpp
defines this class.
//Wrapper header to access/pass std::vector from MATLAB #ifndef cvector_header #define cvector_header #include <vector> template<typename T> class CVector { std::vector<T> data; public: CVector() {} CVector(const std::vector<T>& d): data(d) {} CVector(std::vector<T>&& d) : data(std::move(d)) {} T get(int index) { return data.at(index-1); } void add(const T& element) { data.push_back(element); } const std::vector<T>& getData() const { return data; } }; #endif
To include readStringVector
and
getStringVector
, create a
WrapperStringVector.hpp
header file, which defines
methods to pass CVector
arguments to the C++ library
methods.
// Header that allows the readStringVector and getStringVector functions // to be accessed from MATLAB interface #include "StringVector.hpp" #include "CVector.hpp" #include <string> void wrapperReadStringVector(const CVector<std::string>& stringVec) { readStringVector(stringVec.getData()); } CVector<std::string> wrapperGetStringVector(int size) { auto strVec = getStringVector(size); CVector<std::string> cvecString(strVec); return cvecString; }
Generate the library definition.
clibgen.generateLibraryDefinition(["StringVector.hpp","WrapperStringVector.hpp"],"PackageName","StringVector",... "Libraries","StringVector.lib","TreatObjectPointerAsScalar",true,"Verbose",true)
Build the interface.
build(defineWrapperStringVector)
addpath('WrapperStringVector')
Add the shared library path to the system (run-time) path. If the file is
located on rtPath
, then type:
syspath = getenv('PATH'); rtPath = 'myrtpathname'; setenv('PATH',[rtPath ';' syspath]);
Call the functions.
% Instantiate the CVector class stringVectorObj = clib.StringVector.CVector_std____cxx11__basic_string_char_Std__char_traits_c; % Add elements to vector stringVectorObj.add("Jack"); stringVectorObj.add("John"); stringVectorObj.add("Joe"); % Call function with std::string vector input with CVector clib.StringVector.wrapperReadStringVector(stringVectorObj); clear stringVectorObj;
At the Windows command prompt, add the path to the MinGW-w64 compiler to the system
path. For example, if the compiler is at mingwpath
, then
type:
mingwpath = 'mingwpathname'; set PATH=mingwpath;%PATH%
Navigate to the location of C++ source files.
Run these commands to generate shared library from the source file
:source
.cpp
mingwpath\g++ -c source.cpp -o source.obj -std=c++11 mingwpath\g++ -shared -o source.dll source.obj -Wl,--out-implib,source.lib