Integrate External Code That Uses Pointers, Structures, and Arrays
This example shows how to integrate external code that uses pointers, structures, and arrays into your MATLAB® code. This example demonstrates how to:
Interface with an external structure type by using
coder.cstructname.Interface with an external pointer type by using
coder.opaque.Execute external code by using
coder.ceval.Pass data by reference to external code by using
coder.ref.Instruct the code generator to include the external code by using
coder.updateBuildInfo.Instruct the code generator to use custom data types in standalone code by using the Data type replacement configuration parameter.
Explore the External C Code
The external C code in this example computes the sum of an array of 32-bit integers. Examine the C header file arrayCode.h.
type arrayCode.h#pragma once
#include <stdint.h>
#include "rtwtypes.h"
typedef struct {
int32_T * vals;
int32_T numel;
} myArrayType;
void arrayInit(myArrayType * s, int32_T * temparray);
int32_T arraySum(myArrayType * s);
void arrayDest(myArrayType * s);
The header file defines a custom structure type, myArrayType, that contains a pointer to an array of 32-bit integers and a 32-bit integer. It also declares three C functions:
arrayInitpopulates the array and the number of elements in themyArrayTypestructure.arraySumsums the elements of the array in themyArrayTypestructure.arrayDestdeletes the array and frees the initialized memory.
The file arrayCode.c contains the definitions of these functions. You can customize this C code to change the input types or the computation.
Explore the MATLAB Code
Examine the extSum function.
type extSum.mfunction sum = extSum(size) %#codegen assert(size <= 100) size = int32(size); tempArray = int32(1):size; tempStruct = makeStruct(size); sum = callExtCode(tempStruct,tempArray); end
This function calls the MATLAB functions makeStruct and callExtCode. It constructs a sequential array of 32-bit integers from 1 to the value you pass as the input argument. The function sets an upper bound on the value of the input argument by using an assert statement. Because the constructed array has an upper bound, the generated code does not need to use dynamic memory allocation.
Examine the function makeStruct.
type makeStruct.mfunction myStruct = makeStruct(n)
myStruct.numel = n;
myStruct.vals = coder.opaque('int32_T *','NULL');
coder.cstructname(myStruct,'myArrayType','extern','HeaderFile','arrayCode.h');
end
This function creates a MATLAB structure, myStruct, with fields numel and vals. It defines vals as a pointer to the custom int32_T type by using coder.opaque. The function uses coder.cstructname to specify that the header file arrayCode.h defines the C structure corresponding to myStruct.
Examine the function callExtCode.
type callExtCode.mfunction sum = callExtCode(myStruct,myArray)
sum = int32(0);
coder.updateBuildInfo('addSourceFiles','arrayCode.c');
coder.ceval('arrayInit',coder.ref(myStruct),coder.ref(myArray));
sum = coder.ceval('arraySum',coder.ref(myStruct));
coder.ceval('arrayDest',coder.ref(myStruct));
end
The callExtCode function uses coder.ceval to call the C functions arrayInit, arraySum, and arrayDest. At code generation time, the code generator does not know the type of the output that the C function arraySum returns. So, this function initializes the output variable by using a dummy value. To instruct the code generator to include the file arrayCode.c, the function uses coder.updateBuildInfo.
Generate and Run a MEX Function
You cannot test the extSum function in MATLAB because the MATLAB interpreter does not support many of the functions it uses, including coder.ceval. To test this function, you must generate and run a MEX function.
By default, the codegen command generates a MEX function in C in the working folder. Use the -args option to specify that the input argument is a scalar integer.
codegen extSum -args {0}
Code generation successful.
Test the MEX function against the expected output of the summation. The MEX function produces the same result.
int32(sum(1:50))
ans = int32
1275
extSum_mex(50)
ans = int32
1275
Generate and Inspect C Code
Generate a C static library by using the codegen command with the -config:lib option. Use the same -args syntax that you used to generate the MEX function.
codegen -config:lib extSum -args {0}
Code generation successful.
Examine the declaration of the extSum function in the standalone C code and compare it to the declaration of this function in the MEX code.
mex_file = fullfile("codegen","mex","extSum","extSum.h"); coder.example.extractLines(mex_file,"/* Function Declarations */",";",0,1)
int32_T extSum(const emlrtStack *sp, real_T size);
lib_file = fullfile("codegen","lib","extSum","extSum.h"); coder.example.extractLines(lib_file,"/* Function Declarations */",";",0,1)
extern int extSum(double size);
The MEX function produces an output of type int32_T, which is a MathWorks® type definition. By default, the code generator uses built-in C types for standalone C code and MathWorks types for MEX code. See Mapping MATLAB Types to Types in Generated Code.
Use Custom Data Type in Standalone C Code
To generate standalone code that uses the MathWorks data type int32_T, you must change the default value of the code configuration parameter Data type replacement. To change this value at the command line, first create a configuration object. Then, set the DataTypeReplacement property of the configuration object to "CoderTypedefs".
cfg = coder.config("lib"); cfg.DataTypeReplacement="CoderTypedefs";
Regenerate the C code and pass the configuration object to the codegen command by using the -config option. For this example, use the -d option to generate the code in a new folder.
codegen -config cfg -d newLib extSum -args {0}
Code generation successful.
Examine the declaration of the extSum function in the regenerated standalone C code. The C code uses the custom int32_T datatype.
newlib_file = fullfile("newLib","extSum.h"); coder.example.extractLines(newlib_file,"/* Function Declarations */",";",0,1)
extern int32_T extSum(real_T size);
See Also
codegen | coder.ceval | coder.ref | coder.cstructname | coder.opaque | coder.reservedName