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
(
) as datamodel
_M
Functions essential to executing the model code
To generate a shared library from a model component and use the library, complete the tasks listed in this table.
Task | Action | More Information |
---|---|---|
1 | Review your assessment of external code characteristics and integration requirements. | |
2 | Configure the model for code generation. | Generate Code That Matches Appearance of External Code and Model Configuration |
3 | Configure the model for the code generator to produce a shared library and initiate code generation. | Generate Shared Libraries |
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.
| |
5 | Use the shared library in application code. | Create Application Code That Uses Generated Shared Libraries |
6 | Compile and link application code that loads and uses the generated shared library. | Build Integrated Code Within the Simulink Environment |
7 | Verify that executable program behaves and performs as expected. |
When configuring the model for code generation, select the system target
file ert_shrlib.tlc
.
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.
This example application code is generated for the example Interface to a Development Computer Simulator By Using a Shared Library.
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_*/
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)); }
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); }
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.