Если ваша общая библиотека содержит типы данных или языковые функции, не поддерживаемые MATLAB® интерфейс к библиотекам C++, вы можете включить эту функциональность путем создания файла заголовка оболочки. В этой теме приведены примеры некоторых ограничений. Для получения дополнительной информации смотрите Ограничения на поддержку C/C + +.
Чтобы запустить примеры обходных процессов в Windows®:
Скопируйте операторы файла заголовка C++ в .hpp файлы.
Скопируйте исходный код в .cpp files and build, with instructions in Build Example Shared Library Files on 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 исходный файл, с использованием Пример Shared Library Files в 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 исходный файл, с использованием Пример Shared Library Files в 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 исходный файл, с использованием Пример Shared Library Files в 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