C++ Interface Workaround for Class Objects in std Namespace

8 views (last 30 days)
My C++ code  includes functions that use object defined in the std namespace. How can I include these functions in my C++ Interface?
 

Accepted Answer

MathWorks Support Team
MathWorks Support Team on 22 Feb 2022
Edited: MathWorks Support Team on 31 Jan 2022
A MATLAB interface to a C++ library does not include functions that use objects defined in the std namespace. (For a list of limitations and workarounds see this table .) To get around this limitation, you can add a wrapper class when you build the CPP Interface.
This example shows how to use wraparound functions to access/pass std::stack objects from MATLAB's Cpp Interface.
1. 
*****  Download the complete
used in this example. *****
1. Example code with std::stack
In this example, the functions readStudents and getStudents in the Student.hpp header file have std::stack objects as input or output. If you build the MATLAB interface, these functions are not included due to the limitation on functions using objects defined in the std namespace. The steps below show an example of how to use wraparound functions to get the readStudents and getStudents functionality with the MATLAB interface.
Student.hpp
#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
2. Build a shared library from the original code
Follow the instructions to create a shared library to build a shred library (Student.dll) from the Student.hpp and Student.cpp code.
After building the library, put the Student.hpp header file and Student..lib shared library file in a folder identified as rtpath.
Student.cpp
#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;
}
3. Create a class (CStack) class.
The CStack class encapsulates a std::stack object and functions to add, get, and remove elements from a stack. It contains two functions that are required by the wrapper functions, but are not included in the MATLAB interface: a parameterized constructor that takes a std::stack object as input and a getData function that returns a std::stack object.
CStack.hpp
#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
4. Define wrapper functions
The readStudentWrapper function wraps the readStudents function. It has a CStack object as input and calls the readStudents function with the CStack std::stack object as an input.
The getStudentWrapper function wraps the getStudent function. The std::stack object returned by the getStudent function is used to instantiate the CStack class object using the parameterized constructor. The getStudentWrapper function returns the CStack class object.
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;
}
5. Generate the library definition for the MATLAB Interface.
In this example, the files Student.hpp, StudentWrapper.hpp, and Student.lib are located in the same folder.
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. For the MATLAB interface, you will call the functions readStudentsWrapper and getStudentsWrapper instead of readStudents and getStudents. For the class CStack, the constructor and function getData are used internally and are not callable from the interface.
6. Build the library
build(definestack)
addpath('stack')
7. Use the library.
Add the shared library path to the system (run-time) path. For example, if the shared library file (Student.dll) is located on rtPath, then type:\n\n
syspath = getenv('PATH');
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

More Answers (0)

Tags

No tags entered yet.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!