Generate Reentrant C Code from MATLAB Code - MATLAB & Simulink (original) (raw)

About This Tutorial

Learning Objectives

This tutorial shows you how to:

Note

This example requires libraries that are specific to the Microsoft® Windows® operating system and, therefore, runs only on Windows platforms.

Prerequisites

To complete this example, install the following products:

Required Files

Type Name Description
Function code matrix_exp.m MATLAB function that computes matrix exponential of the input matrix using Taylor series and returns the computed output.
C main function main.c Calls the reentrant code.

About the Example

This example is a simple, multithreaded example that does not use persistent or global data. Two threads call the MATLAB function matrix_exp with different sets of input data.

In your current working folder, create a file matrix_exp.m that contains this code:

function Y = matrix_exp(X) %#codegen % % The function matrix_exp computes matrix exponential of % the input matrix using Taylor series and returns the % computed output. E = zeros(size(X)); F = eye(size(X)); k = 1; while norm(E+F-E,1) > 0 E = E + F; F = X*F/k; k = k+1; end Y = E;

When you generate reusable, reentrant code, MATLAB Coder supports dynamic allocation of:

MATLAB Coder generates a header file, _primaryfunctionname_ _types.h, that you must include when using the generated code. This header file contains the following structures:

Providing a C main Function

To call the reentrant code, provide a main function that:

In your current working folder, create a file main.c that contains this code:

#include <stdio.h> #include <stdlib.h> #include <windows.h> #include "matrix_exp.h" #include "matrix_exp_initialize.h" #include "matrix_exp_terminate.h" #include "rtwtypes.h" #define NUMELEMENTS (160*160) typedef struct { real_T in[NUMELEMENTS]; real_T out[NUMELEMENTS]; matrix_expStackData* spillData; } IODATA; /* The thread_function calls the matrix_exp function written in MATLAB */ DWORD WINAPI thread_function(PVOID dummyPtr) { IODATA *myIOData = (IODATA*)dummyPtr; matrix_exp_initialize(); matrix_exp(myIOData->spillData, myIOData->in, myIOData->out); matrix_exp_terminate(); return 0; } void main() { HANDLE thread1, thread2; IODATA data1; IODATA data2; int32_T i; /*Initializing data for passing to the 2 threads*/ matrix_expStackData* sd1 = (matrix_expStackData*)calloc(1,sizeof(matrix_expStackData)); matrix_expStackData* sd2 = (matrix_expStackData*)calloc(1,sizeof(matrix_expStackData)); data1.spillData = sd1; data2.spillData = sd2; for (i=0;i<NUMELEMENTS;i++) { data1.in[i] = 1; data1.out[i] = 0; data2.in[i] = 1.1; data2.out[i] = 0; } /*Initializing the 2 threads and passing data to the thread functions*/ printf("Starting thread 1...\n"); thread1 = CreateThread(NULL , 0, thread_function, (PVOID) &data1, 0, NULL); if (thread1 == NULL){ perror( "Thread 1 creation failed."); exit(EXIT_FAILURE); } printf("Starting thread 2...\n"); thread2 = CreateThread(NULL, 0, thread_function, (PVOID) &data2, 0, NULL); if (thread2 == NULL){ perror( "Thread 2 creation failed."); exit(EXIT_FAILURE); } /*Wait for both the threads to finish execution*/ if (WaitForSingleObject(thread1, INFINITE) != WAIT_OBJECT_0){ perror( "Thread 1 join failed."); exit(EXIT_FAILURE); } if (WaitForSingleObject(thread2, INFINITE) != WAIT_OBJECT_0){ perror( "Thread 2 join failed."); exit(EXIT_FAILURE); } free(sd1); free(sd2); printf("Finished Execution!\n"); exit(EXIT_SUCCESS); }

Configuring Build Parameters

You can enable generation of reentrant code using a code generation configuration object.

  1. Create a configuration object.
    cfg = coder.config('exe');
  2. Enable reentrant code generation.
    cfg.MultiInstanceCode = true;

Generating the C Code

Call the codegen function to generate C code, with the following options:

codegen -config cfg main.c -report matrix_exp.m -args ones(160,160)

codegen generates a C executable, matrix_exp.exe, in the current folder and C code in the /codegen/exe/matrix_exp subfolder. Because you selected report generation, codegen provides a link to the report.

Viewing the Generated C Code

codegen generates a header file matrix_exp_types.h, which defines the matrix_expStackData global structure. This structure contains local variables that are too large to fit on the stack.

To view this header file:

  1. Click the View report link to open the code generation report.
  2. In the list of generated files, clickmatrix_exp_types.h.
/* * matrix_exp_types.h * * Code generation for function 'matrix_exp' * */ #ifndef __MATRIX_EXP_TYPES_H__ #define __MATRIX_EXP_TYPES_H__ /* Include files */ #include "rtwtypes.h" /* Type Definitions */ #ifndef typedef_matrix_expStackData #define typedef_matrix_expStackData typedef struct { struct { double F[25600]; double Y[25600]; double X[25600]; } f0; } matrix_expStackData; #endif /*typedef_matrix_expStackData*/ #endif /* End of code generation (matrix_exp_types.h) */

Running the Code

Verify that the example is running on Windows platforms and call the code.

% This example can only be run on Windows platforms if ~ispc error('This example requires Windows-specific libraries and can only be run on Windows.'); end system('matrix_exp.exe')

The executable runs and reports completion.

Key Points to Remember

Learn More