Разделяемая библиотека, сгенерированная MATLAB® Compiler SDK™, содержит по крайней мере семь функций. Существует три сгенерированных функции, чтобы справиться с инициализацией библиотеки и завершением, один каждый для печатных выходных сигналов и сообщений об ошибке и двух сгенерированных функций для каждого файла MATLAB, скомпилированного в библиотеку.
Чтобы сгенерировать функции, описанные в этом разделе, сначала скопируйте sierpinski.m
, и triangle.c
, чтобы создать C совместно использовал библиотеку, triangle_legacy.cpp
, чтобы создать API mwArray
C++ совместно использовал библиотеку, или triangle_generic.cpp
, чтобы создать MATLAB Data API C++ совместно использовал библиотеку в вашу директорию. Файлы найдены в
.matlabroot\extern\examples\compilersdk\c_cpp\triangle
Создайте разделяемую библиотеку, как объяснено в, Создают C/C++ Разделяемые Библиотеки из Командной строки. Если ваша разделяемая библиотека создается, выполните следующую команду mbuild
, которая соответствует вашей платформе разработки. Эта команда использует ваш компилятор C/C++, чтобы скомпилировать код и соединиться, код драйвера против MATLAB сгенерировал совместно использованную библиотеку C/C++.
Для приложения C используйте mbuild triangle.c libmatrix.lib
.
Для C++ приложение API mwArray
используйте mbuild triangle_legacy.cpp libtriangle.lib
Для C++ приложение MATLAB Data API используйте mbuild matrix_mda.cpp libtriangle.lib
Расширение .lib
для Windows®. На Mac расширением файла является .dylib
, и на UNIX® это - .so
.
Эта команда принимает, что C/C++ совместно использовал библиотеку, код драйвера, и соответствующий заголовочный файл находится в текущей рабочей папке.
Эти команды создают основную программу под названием triangle
и разделяемую библиотеку под названием libtriangle
. Библиотека экспортирует одну функцию, которая использует простой итеративный алгоритм (содержавшийся в sierpinski.m
), чтобы сгенерировать фрактал, известный как Треугольник Серпинскего. Основная программа в triangle.c
, triangle_legacy.cpp
, triangle_generic.cpp
может опционально взять один числовой аргумент, который, если есть указывает, что число точек раньше генерировало фрактал. Например, triangle 8000
генерирует схему с 8 000 точек.
В этом примере MATLAB Compiler SDK помещает все сгенерированные функции в сгенерированный файл libtriangle.c
или libtriangle.cpp
.
Все программы, которые вызывают сгенерированные совместно использованные библиотеки MATLAB Compiler SDK, имеют примерно ту же структуру:
Объявите переменные и обработайте/подтвердите входные параметры.
Вызовите mclInitializeApplication
и тест для успеха. Эта функция настраивает глобальное состояние MATLAB Runtime и включает конструкцию экземпляров MATLAB Runtime.
Вызовите, однажды для каждой библиотеки, <libraryname>Initialize
, чтобы создать экземпляр MATLAB Runtime, требуемый библиотекой.
Вызовите функции в библиотеке и обработайте результаты. (Это - основная часть программы.)
Вызовите, однажды для каждой библиотеки, <libraryname>Terminate
, чтобы уничтожить связанный MATLAB Runtime.
Вызовите mclTerminateApplication
к бесплатным ресурсам, сопоставленным с глобальным состоянием MATLAB Runtime.
Очистите переменные, близкие файлы, и т.д., и выход.
Чтобы видеть эти шаги в фактическом примере, рассмотрите основную программу в этом примере, triangle.c
.
Функции инициализации и завершения библиотеки создают и уничтожают, соответственно, экземпляр MATLAB Runtime, требуемый разделяемой библиотекой. Необходимо вызвать функцию инициализации, прежде чем вы вызовете любую из других функций в разделяемой библиотеке, и необходимо вызвать функцию завершения после того, как вы закончены, выполнив вызовы в разделяемую библиотеку (или вы рискуете пропускать память).
Существует две формы функции инициализации и один тип функции завершения. Более простая из двух функций инициализации не берет аргументов; скорее всего, это - версия, которую вызовет ваше приложение. В этом примере эта форма функции инициализации называется libtriangleInitialize
.
bool libtriangleInitialize(void)
Эта функция создает экземпляр MATLAB Runtime с помощью печати по умолчанию и обработчиков ошибок и другой информации, сгенерированной во время процесса компиляции.
Однако, если вы хотите больше управления тем, как печатные выходные сигналы и сообщения об ошибке обработаны, можно вызвать вторую форму функции, которая берет два аргумента.
bool libtriangleInitializeWithHandlers( mclOutputHandlerFcn error_handler, mclOutputHandlerFcn print_handler )
Путем вызывания этой функции можно обеспечить собственные версии печати и процедур обработки ошибок, вызванных MATLAB Runtime. Каждая из этих стандартных программ имеет ту же подпись (для полных деталей, смотрите Функции Печати и Обработки ошибок). Путем переопределения значений по умолчанию можно управлять, как выведенный отображен и, например, входит ли это в файл журнала.
Прежде, чем вызвать любую форму стандартной программы инициализации библиотеки, необходимо сначала вызвать mclInitializeApplication
, чтобы настроить глобальное состояние MATLAB Runtime. Смотрите Вызов C Разделяемая Библиотека для получения дополнительной информации.
На платформах Windows Microsoft® MATLAB Compiler SDK генерирует дополнительную функцию инициализации, стандартная функция инициализации Microsoft DLL DllMain
.
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, void *pv)
Сгенерированный DllMain
выполняет очень важный сервис; это определяет местоположение директории, в которой разделяемая библиотека хранится на диске. Эта информация используется, чтобы найти развертываемый архив, без которого не запустится приложение. Если вы изменяете сгенерированный DllMain
(не рекомендуемый), убедитесь, что вы сохраняете эту часть его функциональности.
Завершение библиотеки просто.
void libtriangleTerminate(void)
Вызовите эту функцию (однажды для каждой библиотеки) прежде, чем вызвать mclTerminateApplication
.
По умолчанию MATLAB Compiler SDK сгенерировал приложения и совместно использовал библиотеки, отправляют распечатанный вывод в стандартный вывод и сообщения об ошибке к стандартной погрешности. MATLAB Compiler SDK генерирует обработчик печати по умолчанию и обработчик ошибок по умолчанию, которые проводят эту политику. Если требуется изменить это поведение, необходимо записать собственную ошибку и обработчики печати и передать их в соответствующей сгенерированной функции инициализации.
Можно заменить или, оба или ни одна из этих двух функций. MATLAB Runtime отправляет весь регулярный вывод через обработчик печати и весь вывод ошибок через обработчик ошибок. Поэтому, если вы переопределите любую из этих функций, MATLAB Runtime будет использовать вашу версию функции для всего вывода, который попадает в класс, для которого это вызывает тот обработчик.
Обработчик печати по умолчанию принимает следующую форму.
static int mclDefaultPrintHandler(const char *s)
Реализация является прямой; это берет строку, распечатывает его на стандартном выводе и возвращает количество распечатанных символов. Если вы заменяете или заменяете эту функцию, ваша версия должна также взять строку и возвратить количество “обработанных” символов. MATLAB Runtime вызывает обработчик печати, когда выполняющийся файл MATLAB выполняет запрос для печатного вывода, например, через функцию MATLAB disp
. Обработчик печати не отключает вывод с возвратом каретки или переводом строки.
Обработчик ошибок по умолчанию имеет ту же форму как обработчик печати.
static int mclDefaultErrorHandler(const char *s)
Однако реализация по умолчанию обработчика печати немного отличается. Это отправляет вывод в поток вывода стандартной погрешности, но если строка не заканчивается возвратом каретки, обработчик ошибок добавляет тот. Если вы заменяете обработчик ошибок по умолчанию на одно собственное, необходимо выполнить эту проверку также, или некоторые сообщения об ошибке, распечатанные MATLAB Runtime, не будут правильно отформатированы.
Обработчик ошибок, несмотря на его имя, не обрабатывает фактические ошибки, а скорее сообщение, произведенное после того, как ошибки были зафиксированы и обработаны в MATLAB Runtime. Вы не можете использовать эту функцию, чтобы изменить поведение обработки ошибок MATLAB Runtime - используют операторы try
и catch
в ваших файлах MATLAB, если вы хотите управлять, как сгенерированное приложение MATLAB Compiler SDK отвечает на состояние ошибки.
Если вы обеспечиваете альтернативные реализации C++ или mclDefaultPrintHandler
или mclDefaultErrorHandler
, то функции должны быть объявлены extern "C"
. Например:
extern "C" int myPrintHandler(const char *s);
Для каждого файла MATLAB, заданного на командной строке MATLAB Compiler SDK, продукт генерирует две функции, функцию mlx
и функцию mlf
. Каждая из этих сгенерированных функций выполняет то же действие (вызывает вашу функцию файла MATLAB). Две функции имеют различные имена и представляют различные интерфейсы. Имя каждой функции основано на имени первой функции в файле MATLAB (sierpinski
в этом примере); каждая функция начинается с различного трехбуквенного префикса.
Поскольку C совместно использовал библиотеки, MATLAB Compiler SDK генерирует mlx
и функции mlf
, как описано в этом разделе. Поскольку C++ совместно использовал библиотеки, продукт генерирует функцию mlx
тем же путем, это делает для совместно использованной библиотеки C. Однако продукт генерирует измененную функцию mlf
с этими различиями:
mlf
перед именем функции пропущен, чтобы сохранить совместимость с R13.
Аргументами к функции является mwArray
вместо mxArray
.
Функция, которая начинается с префиксного mlx
, берет тот же тип и количество аргументов как MEX-функция MATLAB. (Дополнительную информацию см. во Внешней документации Интерфейсов относительно MEX-функций.) Первый аргумент, nlhs
, является количеством выходных аргументов, и второй аргумент, plhs
, является указателем на массив, который функция заполнит с требуемым количеством возвращаемых значений. (“lhs
” на эти имена аргумента является сокращением от “левой стороны” - выходные переменные в выражении MATLAB - те на левой стороне оператора присваивания.) Третьи и четвертые параметры являются количеством входных параметров и массива, содержащего входные переменные.
void mlxSierpinski(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
Вторая из сгенерированных функций начинается с префиксного mlf
. Эта функция ожидает, что ее аргументы ввода и вывода будут переданы в как отдельные переменные, а не упакованы в массивы. Если функция способна к созданию одних или нескольких выходных параметров, первый аргумент является количеством выходных параметров, которые требует вызывающая сторона.
void mlfSierpinski(int nargout, mxArray** x, mxArray** y, mxArray* iterations, mxArray* draw)
В обоих случаях сгенерированные функции выделяют память для своих возвращаемых значений. Если вы не удалите эту память (через mxDestroyArray
), когда вы будете сделаны с выходными переменными, ваша программа пропустит память.
Ваша программа может вызвать, какой бы ни из этих функций более удобно, когда они оба вызывают вашу функцию файла MATLAB идентичным способом. Большинство программ, вероятно, вызовет форму mlf
функции, чтобы избежать управления дополнительные массивы, требуемые формой mlx
. Пример программы в triangle.c
вызывает mlfSierpinski
.
mlfSierpinski(2, &x, &y, iterations, draw);
В этом вызове вызывающая сторона запрашивает два выходных аргумента, x
и y
, и обеспечивает два входных параметров, iterations
и draw
.
Если выходные переменные, в которых вы передаете функции mlf
, не будут ПУСТЫМИ, функция mlf
попытается освободить их использующий mxDestroyArray
. Это означает, что можно снова использовать выходные переменные в последовательных вызовах функций mlf
, не волнуясь об утечках памяти. Это также подразумевает, что необходимо передать или NULL
или допустимый массив MATLAB для всех выходных переменных, или программа перестанет работать, потому что диспетчер памяти не может различать неинициализированный (недопустимый) указатель массивов и допустимый массив. Это попытается освободить указатель, который не является ПУСТЫМ - освобождение недопустимого указателя обычно вызывает отказ сегментации или подобную фатальную ошибку.
Если ваш интерфейс функции MATLAB использует varargin
или varargout
, необходимо передать их как массивы ячеек. Например, если у вас есть N
varargin
s, необходимо создать один массив ячеек размера 1-by-N
. Точно так же varargout
s возвращен назад как один массив ячеек. Длина varargout
равна количеству возвращаемых значений, заданных в вызове функции минус количество фактических переданных переменных. Как в программном обеспечении MATLAB, массив ячеек, представляющий varagout
, должен быть последней возвращаемой переменной (переменная, предшествующая первой входной переменной), и массив ячеек, представляющий varargin
, s должен быть последним формальным параметром к вызову функции.
Для получения информации о создании массивов ячеек обратитесь к интерфейсу MEX-функции C во Внешней документации Интерфейсов.
Например, рассмотрите этот интерфейс файла MATLAB:
[a,b,varargout] = myfun(x,y,z,varargin)
Соответствующий интерфейс C для этого
void mlfMyfun(int numOfRetVars, mxArray **a, mxArray **b, mxArray **varargout, mxArray *x, mxArray *y, mxArray *z, mxArray *varargin)
В этом примере числом элементов в varargout
является (numOfRetVars - 2)
, где 2
представляет эти две переменные, a
и b
, будучи возвращенным. И varargin
и varargout
являются одной строкой, несколькими массивами ячейки столбца.
Совместно использованный интерфейс библиотеки C++ не поддерживает varargin
с нулевыми (0) входными параметрами. Вызов вашей программы с помощью пустого mwArray
приводит к группированной библиотеке, получающей пустой массив с nargin = 1
. Совместно использованный интерфейс библиотеки C позволяет вам вызывать mlfFOO(NULL)
(группированный код MATLAB интерпретирует это как nargin=0
). Однако вызов FOO((mwArray)NULL)
с C++ совместно использовал интерфейс библиотеки, заставляет группированный код MATLAB рассматривать пустой массив как первый вход и интерпретирует nargin=1
.
Например, пакет некоторый код MATLAB как C++ совместно использовал библиотеку с помощью varargin
в качестве списка функции MATLAB входных параметров. Имейте отображение кода MATLAB переменная nargin
. Вызовите библиотеку с функциональным
, и это не группирует, производя это сообщение об ошибке:FOO()
... 'FOO' : function does not take 0 arguments
mwArray junk; FOO(junk);
FOO((mwArray)NULL);
nargin=1
. В MATLAB FOO()
является nargin=0
, и FOO([])
является nargin=1
. Интерфейсы C++ для функций MATLAB Используя varargin и varargout. Интерфейс mlx
C++ для функций MATLAB не изменяется, даже если функции используют varargin
или varargout
. Однако C++ функционирует интерфейс (второй набор функций) изменения, если функция MATLAB использует varargin
или varargout
.
Для примеров просмотрите сгенерированный код для различных подписей функции MATLAB, которые используют varargin
или varargout
.
Для простоты только соответствующую часть сгенерированной подписи функции C++ показывают в следующих примерах.
функционируйте varargout = нечто (varargin)
функционируйте varargout = нечто (i1, i2, varargin)
При использовании разделяемых библиотек можно вызвать функции, чтобы получить определенную информацию из состояния MATLAB Runtime. Для получения дополнительной информации смотрите Набор и Получите Данные MATLAB Runtime для Разделяемых Библиотек.