Если ваша общая библиотека содержит типы данных или языковые функции, не поддерживаемые 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