Main Content

Integrate External C Functions That Implement N-Dimensional Table Lookups

Integrate legacy C functions that implement N-dimensional table lookups by using the Legacy Code Tool.

With the Legacy Code Tool, you can:

  • Provide the legacy function specification.

  • Generate a C-MEX S-function that calls the legacy code during simulation.

  • Compile and build the generated S-function for simulation.

  • Generate a TLC block file and optional rtwmakecfg.m file that specifies how the generated code for a model calls the legacy code.

Provide the Legacy Function Specification

Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code() using initialize as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototype of the legacy functions being called in this example is:

FLT directLookupTableND(const FLT *tableND, const UINT32 nbDims, const UINT32 *tableDims, const UINT32 *tableIdx)

FLT is a typedef to float, and UINT32 is a typedef to unsigned int32. The legacy source code is in the files your_types.h, lookupTable.h, and directLookupTableND.c.

defs = [];
evalin('base','load Lct_data.mat')

% sfun_dlut3D
def = legacy_code('initialize');
def.SFunctionName = 'sfun_dlut3D';
def.OutputFcnSpec = 'single y1 = DirectLookupTable3D(single p1[][][], uint32 p2[3], uint32 u1[3])';
def.HeaderFiles   = {'lookupTable.h'};
def.SourceFiles   = {'directLookupTableND.c'};
def.IncPaths      = {'Lct_src'};
def.SrcPaths      = {'Lct_src'};
defs = [defs; def];

% sfun_dlut4D
def = legacy_code('initialize');
def.SFunctionName = 'sfun_dlut4D';
def.OutputFcnSpec = 'single y1 = DirectLookupTable4D(single p1[][][][], uint32 p2[4], uint32 u1[4])';
def.HeaderFiles   = {'lookupTable.h'};
def.SourceFiles   = {'directLookupTableND.c'};
def.IncPaths      = {'Lct_src'};
def.SrcPaths      = {'Lct_src'};
defs = [defs; def];

Generate S-Functions for Simulation

To generate C-MEX S-functions according to the description provided by the input argument defs, call the function legacy_code() again. Set the first input to sfcn_cmex_generate. The S-functions call the legacy functions during simulation. The source code for the S-functions is in the files sfun_dlut3D.c and rtwdemo_sfun_dlut4D.c.

legacy_code('sfcn_cmex_generate', defs);

Compile the Generated S-Functions for Simulation

After you generate the C-MEX S-function source files, to compile the S-functions for simulation with Simulink®, call the function legacy_code() again. Set the first input to compile.

legacy_code('compile', defs);
### Start Compiling sfun_dlut3D
    mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp4b09bd87_d7ea_457f_981e_607028a924f1', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/directLookupTableND.c')
Building with 'gcc'.
MEX completed successfully.
    mex('sfun_dlut3D.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '/tmp/Bdoc24b_2725827_4046264/tp4b09bd87_d7ea_457f_981e_607028a924f1/directLookupTableND.o')
Building with 'gcc'.
MEX completed successfully.
### Finish Compiling sfun_dlut3D
### Exit

### Start Compiling sfun_dlut4D
    mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp7fd0b686_1cd1_4693_91c7_373ad6bcc849', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/directLookupTableND.c')
Building with 'gcc'.
MEX completed successfully.
    mex('sfun_dlut4D.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '/tmp/Bdoc24b_2725827_4046264/tp7fd0b686_1cd1_4693_91c7_373ad6bcc849/directLookupTableND.o')
Building with 'gcc'.
MEX completed successfully.
### Finish Compiling sfun_dlut4D
### Exit

Generate TLC Block Files for Code Generation

After you compile the S-functions and use them in simulation, you can call the function legacy_code() again. Set the first input to sfcn_tlc_generate to generate TLC block files. Block files specify how the generated code for a model calls the legacy code. If you do not generate TLC block files and you try to generate code for a model that includes the S-functions, code generation fails.

legacy_code('sfcn_tlc_generate', defs);

The generated TLC block files for the S-functions are sfun_dlut3D.tlc and sfun_dlut4D.tlc.

Generate an rtwmakecfg.m File for Code Generation

After you create the TLC block files, you can call the function legacy_code() again. Set the first input to rtwmakecfg_generate to generate an rtwmakecfg.m file to support code generation. If the required source and header files for the S-functions are not in the same folder as the S-functions, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m file.

legacy_code('rtwmakecfg_generate', defs);

Generate Masked S-Function Blocks for Calling the Generated S-Functions

After you compile the C-MEX S-function source, you can call the function legacy_code() again. Set the first input to slblock_generate to generate masked S-function blocks that call the S-functions. The software places the blocks in a new model. You can copy the blocks to an existing model.

legacy_code('slblock_generate', defs);

Show the Generated Integration with Legacy Code

The model LctTableLookups shows integration of the model with the legacy code. The subsystem TestLut1 serves as a harness for the call to the legacy C function, and the Display blocks compare the output of the function with the output of the built-in Simulink® lookup blocks. The results are identical.

open_system('LctTableLookups')
open_system('LctTableLookups/TestLut1')
sim('LctTableLookups')
ans =

    '
     ### Start Compiling sfun_dlut3D
         mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp9f4bd3fb_9cb9_4c07_96f3_d5feb4c9fbc1', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/directLookupTableND.c')
     Building with 'gcc'.
     MEX completed successfully.
         mex('sfun_dlut3D.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '/tmp/Bdoc24b_2725827_4046264/tp9f4bd3fb_9cb9_4c07_96f3_d5feb4c9fbc1/directLookupTableND.o')
     Building with 'gcc'.
     MEX completed successfully.
     ### Finish Compiling sfun_dlut3D
     ### Exit
     
     ### Start Compiling sfun_dlut4D
         mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp9f58c049_baa2_43e6_a599_cfeb6e9b3c0a', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/directLookupTableND.c')
     Building with 'gcc'.
     MEX completed successfully.
         mex('sfun_dlut4D.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '/tmp/Bdoc24b_2725827_4046264/tp9f58c049_baa2_43e6_a599_cfeb6e9b3c0a/directLookupTableND.o')
     Building with 'gcc'.
     MEX completed successfully.
     ### Finish Compiling sfun_dlut4D
     ### Exit
     '

See Also

Related Topics