Contenu principal

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:

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:

  • arrayInit populates the array and the number of elements in the myArrayType structure.

  • arraySum sums the elements of the array in the myArrayType structure.

  • arrayDest deletes 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.m
function 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.m
function 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.m
function 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

| | | | |

Topics