Generate Shared Library for Export to External Code Base - MATLAB & Simulink (original) (raw)
Main Content
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.
Generate Shared Libraries
- 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 and the shared library (
.dll
,.so
, or.dylib
file) in the code generation 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.
- 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_SharedLibraryCode;
typedef struct {
int32_T Output;
} ExternalOutputs_SharedLibraryCode;
#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("./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. 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_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);
}
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)
- Variables and signals of type
- Code generation for the
ert_shrlib.tlc
system target file supports the C language only (not C++). When you selectert_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.