主要内容

生成用于导出到外部代码库的共享库

R2026b

关于生成的共享库

如果您有 Embedded Coder® 软件,您可以从模型组件生成共享库 - Windows® 动态链接库 (.dll)、UNIX® 共享对象 (.so) 或 Macintosh OS X 动态库 (.dylib)。您或其他人可以将该共享库集成到在 Windows、UNIX 或 Macintosh OS X 开发计算机上运行的应用程序中。共享库的用途包括:

  • 将软件组件添加到应用程序以进行系统仿真

  • 在开发计算机上的应用程序之间重用软件模块

  • 隐藏与您和供应商共享的软件相关联的知识产权

生成共享库时,代码生成器将执行以下操作:

  • 将 ExportedGlobal 类型的变量和信号导出为数据

  • 将实时模型结构体 (model_M) 导出为数据

  • 导出执行模型代码所必需的函数

工作流

要从模型组件生成共享库并使用此库,请完成下表中列出的任务。

任务操作更多信息
1检查您对外部代码特性和集成要求的评估。
2配置模型以进行代码生成。

Generate Code That Matches Appearance of External Code 模型配置集自定义

3配置模型,使代码生成器生成共享库并启动代码生成。

生成共享库

4

验证生成的共享库满足要求。例如,查看代码生成报告并查看库中的符号列表。

  • 在 Windows 上,使用 Dependency Walker 实用工具,可从 www.dependencywalker.com 下载

  • 在 UNIX 上,使用 nm -D model.so

  • 在 Macintosh OS X 上,使用 nm -g model.dylib

 
5在应用程序代码中使用共享库。

创建使用生成的共享库的应用程序代码

6编译并链接加载和使用生成的共享库的应用程序代码。

在 Simulink 环境中编译集成的代码

7验证可执行程序的行为和性能是否符合预期。

验证、测试和认证

生成共享库

  1. 为代码生成配置模型时,选择系统目标文件 ert_shrlib.tlc。

  2. 编译模型。代码生成器为模型生成源代码以及代码的共享库版本。代码生成器将源代码和共享库(.dll、.so 或 .dylib 文件)放在代码生成文件夹中。代码生成器还生成并保留 .lib 文件以支持隐式链接。

创建使用生成的共享库的应用程序代码

此示例应用程序代码是为示例通过使用共享库对接在开发计算机上运行的仿真器生成的。

  1. 创建一个包含模型外部输入和输出的类型声明的应用程序头文件。例如:

    #ifndef _APP_MAIN_HEADER_
    #define _APP_MAIN_HEADER_
    
    typedef struct {
        int32_T Input;
    } ExternalInputs_SharedLibraryCode;
    
    typedef struct {
        int32_T Output;
    } ExternalOutputs_SharedLibraryCode;
    
    #endif /*_APP_MAIN_HEADER_*/
  2. 在应用程序 C 源代码中,动态加载共享库。使用预处理条件语句调用特定于平台的命令。例如:

    #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("./SharedLibraryCode_win64.dll");
    #else #if defined(_WIN32) 
        handleLib = LOADLIB("./SharedLibraryCode_win32.dll");
    #else /* UNIX */     
        handleLib = LOADLIB("./SharedLibraryCode.so", RTLD_LAZY); 
    #endif 
    #endif 
    ...     
        return(CLOSELIB(handleLib)); 
    }
  3. 从应用程序 C 源代码访问从模型导出的数据和生成的函数。代码使用钩子添加用户定义的初始化、步进和终止代码。

       int32_T i;
     ...
        void (*mdl_initialize)(boolean_T);
        void (*mdl_step)(void);
        void (*mdl_terminate)(void);
    
        ExternalInputs_SharedLibraryCode (*mdl_Uptr);
        ExternalOutputs_SharedLibraryCode (*mdl_Yptr);
            
        uint8_T (*sum_outptr);
    ...
    #if (defined(BORLANDCDLL))
        /* Exported symbols contain leading underscores 
           when DLL is linked with BORLANDC */
        mdl_initialize =
            (void(*)(boolean_T))GETSYMBOLADDR(handleLib ,
            "_SharedLibraryCode_initialize");
        mdl_step =
            (void(*)(void))GETSYMBOLADDR(handleLib ,
            "_SharedLibraryCode_step");
        mdl_terminate =
            (void(*)(void))GETSYMBOLADDR(handleLib ,
            "_SharedLibraryCode_terminate");
        mdl_Uptr =
            (ExternalInputs_SharedLibraryCode*)GETSYMBOLADDR(handleLib ,
            "_SharedLibraryCode_U");
        mdl_Yptr =
            (ExternalOutputs_SharedLibraryCode*)GETSYMBOLADDR(handleLib ,
            "_SharedLibraryCode_Y");
        sum_outptr =
            (uint8_T*)GETSYMBOLADDR(handleLib , "_sum_out");
    #else   
        mdl_initialize =
            (void(*)(boolean_T))GETSYMBOLADDR(handleLib ,
            "SharedLibraryCode_initialize");
        mdl_step =
            (void(*)(void))GETSYMBOLADDR(handleLib ,
            "SharedLibraryCode_step");
        mdl_terminate  =
            (void(*)(void))GETSYMBOLADDR(handleLib ,
            "SharedLibraryCode_terminate");
        mdl_Uptr =
            (ExternalInputs_SharedLibraryCode*)GETSYMBOLADDR(handleLib ,
            "SharedLibraryCode_U");
        mdl_Yptr =
            (ExternalOutputs_SharedLibraryCode*)GETSYMBOLADDR(handleLib ,
            "SharedLibraryCode_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);
        }

限制

  • 针对 ert_shrlib.tlc 系统目标文件的代码生成会将以下内容导出为数据:

    • ExportedGlobal 类型的变量和信号

    • 实时模型结构 (model_M)

  • ert_shrlib.tlc 系统目标文件的代码生成仅支持 C 语言(不支持 C++)。当您选择 ert_shrlib.tlc 时,语言选择在“配置参数”对话框的代码生成窗格上不可用。

  • 要使用生成的共享库重新构造模型仿真,应用程序作者必须保持原始应用程序中系统和共享库函数调用之间的时序。时序必须一致,以便您比较仿真和集成结果。如果从启用了模型配置参数支持连续时间和单一输出/更新函数的模型生成共享库,则需要考虑其他仿真因素。

另请参阅

主题