Main Content

Generate Shared Library for Export to External Code Base

About Generated Shared Libraries

If you have Embedded Coder® software, you can generate a shared library—Windows® dynamic link library (.dll), UNIX® shared object (.so), or Macintosh OS X dynamic library (.dylib)— from a model component. You or others can integrate the shared library into an application that runs on a Windows, UNIX, or Macintosh OS X development computer. Uses of shared libraries include:

  • Adding a software component to an application for system simulation

  • Reusing software modules among applications on a development computer

  • Hiding intellectual property associated with software that you share with vendors

When producing a shared library, the code generator exports:

  • Variables and signals of type ExportedGlobal as data

  • Real-time model structure (model_M) as data

  • Functions essential to executing the model code

Workflow

To generate a shared library from a model component and use the library, complete the tasks listed in this table.

TaskActionMore Information
1Review your assessment of external code characteristics and integration requirements.
2Configure the model for code generation.Generate Code That Matches Appearance of External Code (Embedded Coder) and Model Configuration (Embedded Coder)
3Configure the model for the code generator to produce a shared library and initiate code generation.Generate Shared Libraries (Embedded Coder)
4

Verify that the generated shared library meets requirements. For example, review the code generation report and view the list of symbols in the library.

  • On Windows, use the Dependency Walker utility, downloadable from www.dependencywalker.com

  • On UNIX, use nm -D model.so

  • On Macintosh OS X, use nm -g model.dylib

 
5Use the shared library in application code.Create Application Code That Uses Generated Shared Libraries (Embedded Coder)
6Compile and link application code that loads and uses the generated shared library.Build Integrated Code Within the Simulink Environment (Embedded Coder)
7Verify that executable program behaves and performs as expected.

Generate Shared Libraries

  1. When configuring the model for code generation, select the system target file ert_shrlib.tlc.

  2. Build the model. The code generator produces source code for the model and a shared library version of the code. The code generator places the source code in the code generation folder and the shared library (.dll, .so, or .dylib file) in your current working folder. The code generator also produces and retains a .lib file to support implicit linking.

Create Application Code That Uses Generated Shared Libraries

This example application code is generated for the example Interface to a Development Computer Simulator By Using a Shared Library (Embedded Coder).

  1. Create an application header file that contains type declarations for model external input and output. For example:

    #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_*/
  2. In the application C source code, dynamically load the shared library. Use preprocessing conditional statements to invoke platform-specific commands. For example:

    #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)); 
    }
  3. From the application C source code, access exported data and functions generated from the model. The code uses hooks to add user-defined initialization, step, and termination code.

       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);
        }

Limitations

  • Code generation for the ert_shrlib.tlc system target file exports the following as data:

    • Variables and signals of type ExportedGlobal

    • Real-time model structure (model_M)

  • Code generation for the ert_shrlib.tlc system target file supports the C language only (not C++). When you select ert_shrlib.tlc, language selection is unavailable on the Code Generation pane in the Configuration Parameters dialog box.

  • To reconstruct a model simulation by using a generated shared library, the application author must maintain the timing between system and shared library function calls in the original application. The timing must be consistent so that you can compare the simulation and integration results. Additional simulation considerations apply if generating a shared library from a model that enables model configuration parameters Support: continuous time and Single output/update function. For more information, see Single output/update function (Simulink Coder) dependencies.

Related Topics