If you have an Embedded Coder® license, you can package generated source code from a model component for easy
distribution and shared use by building the code as a shared library—Windows® dynamic link library (.dll
), UNIX® shared object (.so
), or Macintosh OS X dynamic library (.dylib
). You or others can integrate the
shared library into an application that runs on a Windows, UNIX, or Macintosh OS X development computer. The generated .dll
,
.so
, or .dylib
file is shareable among different
applications and upgradeable without having to recompile the applications that use
it.
You build a shared library by configuring the code generator
to use the system target file ert_shrlib.tlc
. Code
generation for that system target file exports:
Variables and signals of type ExportedGlobal
as
data
Real-time model structure (
)
as datamodel
_M
Functions essential to executing your model code
To view a list of symbols contained in a generated shared library:
On Windows, use the Dependency Walker utility, downloadable from http://www.dependencywalker.com
On UNIX, use nm -D
model
.so
On Macintosh OS X , use nm -g
model
.dylib
To generate and use a shared library:
Generate a shared library version of your model code
Create application code to load and use your shared library file
To generate a shared library version of your model code:
Open your model and configure it to use the ert_shrlib.tlc
system
target file.
Selecting the ert_shrlib.tlc
system target
file causes the build process to generate a shared library version
of your model code into your current working folder. The selection
does not change the code that the code generator produces for your
model.
Build the model.
After the build completes, examine the generated code
in the model subfolder and examine the .dll
, .so
,
or .dylib
file in your current folder.
To illustrate how application code can load a shared library
file and access its functions and data, MathWorks provides the model rtwdemo_shrlib
.
Note
Navigate to a writable working folder before running the
rtwdemo_shrlib
script.
In the model, click the blue button to run a script. The script:
Builds a shared library file from the model (for
example, rtwdemo_shrlib_win64.dll
on 64-bit Windows).
Compiles and links an example application, rtwdemo_shrlib_app
,
that loads and uses the shared library file.
Executes the example application.
Tip
Explicit linking is preferred for portability. However, on Windows systems, the ert_shrlib
system target file
generates and retains the .lib
file to support implicit
linking.
To use implicit linking, the generated header file needs a small modification for you to use
it with the generated C file. For example, if you are using Visual C++®, declare __declspec(dllimport)
in front of data to
be imported implicitly from the shared library file.
The model uses the following example application files, which
are located in the folder
(open).matlabroot
/toolbox/rtw/rtwdemos/shrlib_demo
File | Description |
---|---|
rtwdemo_shrlib_app.h | Example application header file |
rtwdemo_shrlib_app.c | Example application that loads and uses the shared library file generated for the model |
run_rtwdemo_shrlib_app.m | Script to compile, link, and execute the example application |
You can view each of these files by clicking white buttons in the model window. Additionally, running the script places the relevant source and generated code files in your current folder. The files can be used as templates for writing application code for your own ERT shared library files.
The following sections present key excerpts of the example application files.
The example application header file rtwdemo_shrlib_app.h
contains
type declarations for the model's external input and output.
#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_*/
The example application rtwdemo_shrlib_app.c
includes
the following code for dynamically loading the shared library file.
Notice that, depending on platform, the code invokes Windows or UNIX library
commands.
#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)); }
The following code excerpt shows how the C application accesses the model's exported data and functions. Notice the hooks for adding 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); }
The application script run_rtwdemo_shrlib_app
loads
and rebuilds the model, and then compiles, links, and executes the
model's shared library target file. You can view the script source
file by opening rtwdemo_shrlib
and
clicking a white button to view source code. The script constructs
platform-dependent command character vectors for compilation, linking,
and execution that may apply to your development environment. To run
the script, click the blue button.
Note
To run the run_rtwdemo_shrlib_app
script without first
opening the rtwdemo_shrlib
model, navigate to a writable
working folder and issue the following MATLAB® command:
addpath(fullfile(matlabroot,'toolbox','rtw','rtwdemos','shrlib_demo'))
Note
It is invalid to invoke the terminate function twice in a row. The terminate function clears pointers and sets them to NULL. Invoking the function a second time dereferences null pointers and results in a program failure.
The following limitations apply to building shared libraries:
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
For a model that contains a function-call subsystem, code generation for the
ert_shrlib.tlc
system target file exports to the shared
library only symbols associated with the initialize and terminate entry-point
functions.
Code generation for the ert_shrlib.tlc
system target file
supports the C language only (not C++). When you select
ert_shrlib.tlc
, model configuration parameter
Language is greyed out.
To reconstruct a model simulation 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 needs to 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 dependencies.