Если общая библиотека содержит типы данных или языковые функции, не поддерживаемые интерфейсом MATLAB ® для библиотек C++, можно включить эту функцию, создав файл заголовка оболочки. В этом разделе приведены примеры некоторых ограничений. Дополнительные сведения см. в разделе Ограничения поддержки C/C + +.
Чтобы запустить обходные примеры в Windows ®:
Скопируйте инструкции файла заголовка C++ в .hpp файлы.
Копирование исходного кода в .cpp файлы и сборка, используя инструкции в разделе Создание примеров файлов общей библиотеки в Windows.
Выполните код MATLAB для построения интерфейса.
При необходимости отредактируйте файл определения библиотеки.
Выполните код MATLAB для тестирования функциональных возможностей.
std Пространство именИнтерфейс MATLAB с библиотекой C++ не включает функции, использующие объекты, определенные в std пространство имен. Например, функции в этом Student.hpp передача файла заголовка std::stack объекты. При построении интерфейса MATLAB, функции readStudents и getStudents не включены.
#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Чтобы запустить этот пример в Windows, создайте Student.lib и Student.dll файлы из этого Student.cpp с помощью команды «Создать пример файлов общей библиотеки в 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;
}Создать Student.hpp заголовочный файл и поместите его вместе с Student.dll файл общей библиотеки в папке, идентифицированной как rtpath.
Создание класса CStack для представления std::stack объект. Поместить это определение в файл заголовка 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Определение функции readStudentsWrapper для вызова readStudents с помощью функции CStack класс и getStudentsWrapper для вызова getStudents функция. Включить эти функции в файл заголовка оболочки с именем 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;
}Создание определения библиотеки в пакете с именем 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).
Игнорировать Did not add сообщения. В MATLAB вызываются функции readStudentsWrapper и getStudentsWrapper вместо readStudents и getStudents. Конструктор для класса CStack и член getData используются внутри и не вызываются из интерфейса.
Создайте интерфейс.
build(definestack)
addpath('stack')Добавьте путь к общей библиотеке к системному пути (времени выполнения). Если файл расположен на rtPath, затем введите:
syspath = getenv('PATH'); rtPath = 'myrtpathname'; setenv('PATH',[rtPath ';' syspath]);
Звонить 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)
Звонить getStudentsWrapper.
clear studentsStack; studentsStack = clib.stack.getStudentsWrapper(3); student = studentsStack.get; % returns topmost element from studentStack studentsStack.remove % removes topmost element of stack
Интерфейс MATLAB с библиотекой C++ не поддерживает неподтвержденные классы шаблонов. Например, класс Pairs в этом Templates.hpp не создан экземпляр файла заголовка.
// 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Чтобы включить Pairs класс, создайте этот файл заголовка оболочки TemplatesWrapper.hpp. Предположим, что Pairs поддержки int и double типы данных.
//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>;
Создайте определение библиотеки.
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(defineTemplates)
addpath('Templates')Создать Pairs объекты и вызовите getVal1 и getVal2 функции.
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;
Интерфейс MATLAB с библиотекой C++ не поддерживает директивы препроцессора (макросы). Например, это Area.hpp файл заголовка определяет макрос PI. При построении интерфейса MATLAB PI не включен.
//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Чтобы запустить этот пример в Windows, создайте Area.lib и Area.dll файлы из этого Area.cpp с помощью команды «Создать пример файлов общей библиотеки в Windows».
#define EXPORT
#include "Area.hpp"
DLL_EXPORT double getArea(int radius, double piVal) {
return piVal*radius*radius;
}Создать Area.hpp заголовочный файл и поместите его вместе с Area.dll файл общей библиотеки в папке, идентифицированной как rtpath.
Включать PI, создайте этот файл заголовка оболочки WrapperPI.hpp который определяет функцию getPI для получения значения директивы препроцессора.
//Wrapper to access the preprocessor directive value
#include "Area.hpp"
double getPI(){ //Wrapper function retrieves the value of PI
return PI;
}Создайте определение библиотеки.
clibgen.generateLibraryDefinition(["Area.hpp","WrapperPI.hpp"],"PackageName","Area",... "Libraries","Area.lib","TreatObjectPointerAsScalar",true,"Verbose",true)
Создайте интерфейс.
build(defineArea)
addpath('Area')Добавьте путь к общей библиотеке к системному пути (времени выполнения). Если файл расположен на rtPath, затем введите:
syspath = getenv('PATH'); rtPath = 'myrtpathname'; setenv('PATH',[rtPath ';' syspath]);
Звонить getArea.
pi = clib.Area.getPI; area = clib.Area.getArea(2,pi)
area = 12.5660
Интерфейс MATLAB к библиотеке C++ не включает функции с аргументами std::string для типа элемента вектора. Например, readStringVector и getStringVector функции в этом StringVector.hpp не включаются при построении интерфейса MATLAB.
//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Чтобы запустить этот пример в Windows, создайте StringVector.lib и StringVector.dll файлы из этого StringVector.cpp с помощью команды «Создать пример файлов общей библиотеки в 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;
}Создать StringVector.hpp заголовочный файл и поместите его вместе с StringVector.dll файл общей библиотеки в папке, идентифицированной как rtpath.
Поддерживать std::vector типа std::string, создайте CVector , который определяет эти методы для передачи std::vector между MATLAB и библиотекой.
Параметризованный конструктор:
CVector(const std::vector<T>& d): data(d)
Конструктор перемещения:
CVector(std::vector<T>&& d) : data(std::move(d))
Метод доступа к элементу по индексу:
T get(int index)
Метод добавления элементов к векторам:
void add(const T& element)
Способ получения данных из векторов:
const std::vector<T>& getData() const
CVector.hpp определяет этот класс.
//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Включать readStringVector и getStringVector, создайте WrapperStringVector.hpp файл заголовка, определяющий методы для передачи CVector аргументы для методов библиотеки C++.
// 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;
}Создайте определение библиотеки.
clibgen.generateLibraryDefinition(["StringVector.hpp","WrapperStringVector.hpp"],"PackageName","StringVector",... "Libraries","StringVector.lib","TreatObjectPointerAsScalar",true,"Verbose",true)
Создайте интерфейс.
build(defineWrapperStringVector)
addpath('WrapperStringVector')Добавьте путь к общей библиотеке к системному пути (времени выполнения). Если файл расположен на rtPath, затем введите:
syspath = getenv('PATH'); rtPath = 'myrtpathname'; setenv('PATH',[rtPath ';' syspath]);
Вызовите функции.
% 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;
В командной строке Windows добавьте путь к компилятору MinGW-w64 к системному пути. Например, если компилятор имеет значение mingwpath, затем введите:
mingwpath = 'mingwpathname'; set PATH=mingwpath;%PATH%
Перейдите в расположение исходных файлов C++.
Выполнение этих команд для создания общей библиотеки из исходного файла :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