Упаковать сгенерированный код как общие библиотеки

Если у вас есть Embedded Coder® лицензия, можно упаковать сгенерированный исходный код из компонента модели для простого распределения и совместного использования путем создания кода как общей библиотеки - Windows® библиотека динамических ссылок (.dll), UNIX® общий объект (.so), или динамическая библиотека Macintosh OS X (.dylib). Вы или другие пользователи можете интегрировать общую библиотеку в приложение, работающее на компьютере разработчика Windows, UNIX или Macintosh OS X. Сгенерированный .dll, .so, или .dylib файл доступен совместно для различных приложений и может быть обновлен без необходимости перекомпиляции приложений, которые его используют.

Сведения о сгенерированных общих библиотеках

Вы создаете общую библиотеку, конфигурируя генератор кода, чтобы использовать системный целевой файл ert_shrlib.tlc. Генерация кода для этого системного целевого файла экспортов:

  • Переменные и сигналы типа ExportedGlobal как данные

  • Структура модели реального времени (model_M) как данные

  • Функции, необходимые для выполнения кода модели

Чтобы просмотреть список символов, содержащихся в сгенерированной общей библиотеке:

  • В Windows используйте утилиту Dependency Walker, загружаемую из http://www.dependencywalker.com

  • В UNIX используйте nm -D model.so

  • В Macintosh OS X используйте nm -g model.dylib

Чтобы сгенерировать и использовать общую библиотеку:

  1. Сгенерируйте общую библиотечную версию кода модели

  2. Создайте код приложения для загрузки и использования вашего файла общей библиотеки

Сгенерируйте общую библиотечную версию кода модели

Чтобы сгенерировать общую библиотечную версию вашего кода модели:

  1. Откройте модель и сконфигурируйте ее, чтобы использовать ert_shrlib.tlc системный целевой файл.

    Выбор ert_shrlib.tlc системный целевой файл заставляет процесс сборки сгенерировать общую библиотечную версию кода модели в текущую рабочую папку. Выбор не меняет код, который производит генератор кода для вашей модели.

  2. Создайте модель.

  3. После завершения сборки исследуйте сгенерированный код в подпапке модели и исследуйте .dll, .so, или .dylib файл в текущей папке.

Создайте код приложения для использования общей библиотеки

Чтобы проиллюстрировать, как код приложения может загрузить файл общей библиотеки и получить доступ к его функциям и данным, MathWorks предоставляет модель rtwdemo_shrlib.

Примечание

Перейдите в рабочую папку с возможностью записи перед запуском rtwdemo_shrlib скрипт.

В модели нажмите синюю кнопку, чтобы запустить скрипт. Скрипт:

  1. Создает файл общей библиотеки из модели (для примера, rtwdemo_shrlib_win64.dll в 64-разрядной версии Windows).

  2. Компилирует и связывает пример приложения, rtwdemo_shrlib_app, который загружает и использует файл общей библиотеки.

  3. Выполняет пример приложения.

Совет

Явное связывание предпочтительно для переносимости. Однако в системах Windows ert_shrlib системный целевой файл генерирует и сохраняет .lib файл для поддержки неявной ссылки.

Чтобы использовать неявную ссылку, сгенерированный файл заголовка нуждается в небольшой модификации, чтобы вы использовали его с сгенерированным файлом C. Для примера, если вы используете Visual C++®, объявить __declspec(dllimport) перед данными, которые будут неявно импортированы из файла общей библиотеки.

Модель использует следующие примеры файлов приложения, которые находятся в папке matlabroot/ toolbox/rtw/rtwdemos/shrlib_demo (откройте).

ФайлОписание
rtwdemo_shrlib_app.hПример файла заголовка приложения
rtwdemo_shrlib_app.cПример приложения, которое загружает и использует файл общей библиотеки, сгенерированный для модели
run_rtwdemo_shrlib_app.mСкрипт для компиляции, связывания и выполнения примера приложения

Можно просмотреть каждый из этих файлов, нажав белые кнопки в окне модели. Кроме того, выполнение скрипта помещает соответствующие исходные и сгенерированный код файлы в текущую папку. Файлы могут использоваться в качестве шаблонов для записи кода приложения для ваших собственных общих файлов библиотеки ERT.

В следующих разделах представлены ключевые выдержки из примерных файлов приложения.

Пример файла заголовка приложения

Пример файла заголовка приложения rtwdemo_shrlib_app.h содержит объявления типов для внешних входных и выходных входов модели.

#ifndef _APP_MAIN_HEADER_
#define _APP_MAIN_HEADER_

typedef struct {
    int32_T Input;
} ExternalInputs_rtwdemo_shrlib;

typedef struct {
    int32_T Output;
} ExternalOutputs_rtwdemo_shrlib;

#endif /*_APP_MAIN_HEADER_*/

Пример применения кода С

Пример приложения rtwdemo_shrlib_app.c включает следующий код для динамической загрузки файла общей библиотеки. Заметьте, что, в зависимости от платформы, код вызывает команды библиотеки Windows или UNIX.

#if (defined(_WIN32)||defined(_WIN64)) /* WINDOWS */
#include <windows.h>
#define GETSYMBOLADDR GetProcAddress
#define LOADLIB LoadLibrary
#define CLOSELIB FreeLibrary

#else /* UNIX */
#include <dlfcn.h>
#define GETSYMBOLADDR dlsym
#define LOADLIB dlopen
#define CLOSELIB dlclose

#endif

int main()
{
    void* handleLib;
...
#if defined(_WIN64)
    handleLib = LOADLIB("./rtwdemo_shrlib_win64.dll");
#else
#if defined(_WIN32)
    handleLib = LOADLIB("./rtwdemo_shrlib_win32.dll");
#else /* UNIX */
    handleLib = LOADLIB("./rtwdemo_shrlib.so", RTLD_LAZY);
#endif
#endif
...
    return(CLOSELIB(handleLib));
}

Следующий фрагмент кода показывает, как приложение C обращается к экспортированным данным и функциям модели. Обратите внимание на крючки для добавления пользовательского кода инициализации, шага и завершения.

    int32_T i;
 ...
    void (*mdl_initialize)(boolean_T);
    void (*mdl_step)(void);
    void (*mdl_terminate)(void);

    ExternalInputs_rtwdemo_shrlib (*mdl_Uptr);
    ExternalOutputs_rtwdemo_shrlib (*mdl_Yptr);
        
    uint8_T (*sum_outptr);
...
#if (defined(LCCDLL)||defined(BORLANDCDLL))
    /* Exported symbols contain leading underscores when DLL is linked with
       LCC or BORLANDC */
    mdl_initialize =(void(*)(boolean_T))GETSYMBOLADDR(handleLib ,
                     "_rtwdemo_shrlib_initialize");
    mdl_step       =(void(*)(void))GETSYMBOLADDR(handleLib ,
                     "_rtwdemo_shrlib_step");
    mdl_terminate  =(void(*)(void))GETSYMBOLADDR(handleLib ,
                     "_rtwdemo_shrlib_terminate");
    mdl_Uptr       =(ExternalInputs_rtwdemo_shrlib*)GETSYMBOLADDR(handleLib ,
                     "_rtwdemo_shrlib_U");
    mdl_Yptr       =(ExternalOutputs_rtwdemo_shrlib*)GETSYMBOLADDR(handleLib ,
                     "_rtwdemo_shrlib_Y");
    sum_outptr     =(uint8_T*)GETSYMBOLADDR(handleLib , "_sum_out");
#else   
    mdl_initialize =(void(*)(boolean_T))GETSYMBOLADDR(handleLib ,
                     "rtwdemo_shrlib_initialize");
    mdl_step       =(void(*)(void))GETSYMBOLADDR(handleLib ,
                     "rtwdemo_shrlib_step");
    mdl_terminate  =(void(*)(void))GETSYMBOLADDR(handleLib ,
                     "rtwdemo_shrlib_terminate");
    mdl_Uptr       =(ExternalInputs_rtwdemo_shrlib*)GETSYMBOLADDR(handleLib ,
                     "rtwdemo_shrlib_U");
    mdl_Yptr       =(ExternalOutputs_rtwdemo_shrlib*)GETSYMBOLADDR(handleLib ,
                     "rtwdemo_shrlib_Y");
    sum_outptr     =(uint8_T*)GETSYMBOLADDR(handleLib , "sum_out");
#endif
    
    if ((mdl_initialize && mdl_step && mdl_terminate && mdl_Uptr && mdl_Yptr && 
         sum_outptr)) {
        /* === user application initialization function === */
        mdl_initialize(1); 
        /* insert other user defined application initialization code here */
        
        /* === user application step function === */
        for(i=0;i<=12;i++){ 
            mdl_Uptr->Input = i;
            mdl_step(); 
            printf("Counter out(sum_out): %d\tAmplifier in(Input): %d\tout(Output): %d\n",
                   *sum_outptr, i, mdl_Yptr->Output); 
            /* insert other user defined application step function code here */
        }
        
        /* === user application terminate function === */
        mdl_terminate();
        /* insert other user defined application termination code here */
    }
    else {
        printf("Cannot locate the specified reference(s) in the shared library.\n");
        return(-1);
    }

Пример скрипта приложения

Скрипт приложения run_rtwdemo_shrlib_app загружает и перестраивает модель, а затем компилирует, связывает и выполняет целевой файл общей библиотеки модели. Вы можете просмотреть исходный файл скрипта, открывая rtwdemo_shrlib и нажатие белой кнопки для просмотра исходного кода. Скрипт создает зависящие от платформы команды векторов символов для компиляции, связывания и выполнения, которые могут применяться к среде разработки. Чтобы запустить скрипт, нажмите синюю кнопку.

Примечание

Чтобы запустить run_rtwdemo_shrlib_app скрипт, не открывая rtwdemo_shrlib модель, перейдите к рабочей папке с возможностью записи и выпустите следующий MATLAB® команда:

addpath(fullfile(matlabroot,'toolbox','rtw','rtwdemos','shrlib_demo'))

Примечание

Недопустимо вызывать функцию terminate дважды в строку. Функция terminate очищает указатели и устанавливает их в NULL. Вызов функции во второй раз выдает ядро указателей и приводит к отказу программы.

Ограничения, накладываемые на общую библиотеку

Следующие ограничения применяются к созданию общих библиотек:

  • Генерация кода для ert_shrlib.tlc системный целевой файл экспортирует следующее как данные:

    • Переменные и сигналы типа ExportedGlobal

    • Структура модели реального времени (model_M)

  • Для модели, которая содержит подсистему вызова функций, генерация кода для ert_shrlib.tlc системный целевой файл экспортирует в общую библиотеку только символы, сопоставленные с функциями инициализации и завершения работы точки входа.

  • Генерация кода для ert_shrlib.tlc системный целевой файл поддерживает только язык C (не C++). Когда вы выбираете ert_shrlib.tlc, параметр конфигурации модели Language затемнен.

  • Чтобы восстановить симуляцию модели с помощью сгенерированной общей библиотеки, автор приложения должен поддерживать синхронизацию между вызовами системных и общих библиотечных функций в исходном приложении. Синхронизация должна быть последовательной, чтобы можно было сравнить результаты симуляции и интегрирования. Дополнительные факторы симуляции применяются, если генерируется общая библиотека из модели, которая позволяет параметры конфигурации <reservedrangesplaceholder1> и <reservedrangesplaceholder0> модели. Для получения дополнительной информации смотрите Single output/update function dependencies.

Похожие темы

Для просмотра документации необходимо авторизоваться на сайте