External Function Calls from Generated Code

Calling External Functions from Generated Code

You can call external functions from generated code. The external functions must have a C programming interface. The code generator provides functions for:

  • Calling external functions from generated code.

  • Passing arguments by reference to external code.

  • Manipulating C/C++ data.

By using these functions, you gain unrestricted access to external code. Misuse of these functions or errors in your code can destabilize MATLAB® when generating MEX functions.

Why Call External Functions from Generated Code?

Call external functions from generated code when you want to:

  • Use legacy code.

  • Use your own optimized functions instead of generated code.

  • Interface your libraries and hardware with MATLAB functions.

How To Call External Functions

To call external functions, use one of the following methods:

  • The coder.ceval function in your MATLAB code. coder.ceval passes function input and output arguments to C/C++ functions by value or by reference.

  • The coder.ExternalDependency class to define methods that call the functions. These methods use the coder.ceval function. In your MATLAB code, use these methods to call external functions.

Define the called functions in external C/C++ source files, object files, or libraries. You must then include C/C++ source files, libraries, object files, and header files in the build configuration. See Specify External File Locations.

Pass Arguments by Reference to External Functions

By default, coder.ceval passes arguments by value to the C/C++ function whenever C/C++ supports passing arguments by value. You can pass MATLAB variables as arguments by reference to external C/C++ functions with the following constructs:

These constructs offer the following benefits:

  • Passing values by reference optimizes memory use.

    When you pass arguments by value, MATLAB Coder™ passes a copy of the value of each argument to the C/C++ function to preserve the original values. When you pass arguments by reference, MATLAB Coder does not copy values. If you need to pass large matrices to the C/C++ function, the memory savings can be significant.

    Passing write-only values by reference allows you to return multiple outputs.

    Use coder.wref to return multiple outputs from your C/C++ function, including arrays and matrices. Otherwise, the C/C++ function can return only a single scalar value through its return statement.

Do not store pointers that you pass to C/C++ functions because MATLAB Coder optimizes the code based on the assumption that you do not store the addresses of these variables. Storing the addresses might invalidate our optimizations leading to incorrect behavior. For example, if a MATLAB function passes a pointer to an array using coder.ref, coder.rref, or coder.wref, then the C/C++ function can modify the data in the array—but you should not store the pointer for future use.

When you pass arguments by reference using coder.rref, coder.wref, and coder.ref, the corresponding C/C++ function signature must declare these variables as pointers of the same data type. Otherwise, the C/C++ compiler generates a type mismatch error.

For example, suppose your MATLAB function calls an external C function ctest:

function y = fcn()
u = pi;

y = 0;
y = coder.ceval('ctest',u);

Now suppose the C function signature is:

double ctest(double *a)

When you compile the code, you get a type mismatch error because coder.ceval calls ctest with an argument of type double when ctest expects a pointer to a double-precision, floating-point value.

Match the types of arguments in coder.ceval with their counterparts in the C function. For instance, you can fix the error in the previous example by passing the argument by reference:

y = coder.ceval('ctest', coder.rref(u));

You can pass a reference to an element of a matrix. For example, to pass the second element of the matrix v, you can use the following code:

y = coder.ceval('ctest', coder.ref(v(1,2)));

Manipulate C Data

The construct coder.opaque allows you to manipulate C/C++ data that a MATLAB function does not recognize. You can store the opaque data in a variable or structure field and pass it to, or return it from, a C/C++ function using coder.ceval.

Declaring Opaque Data

The following example uses coder.opaque to declare a variable f as a FILE * type.

% This example returns its own source code by using 
% fopen/fread/fclose.
function buffer = filetest 
%#codegen

% Declare 'f' as an opaque type 'FILE *'
f = coder.opaque('FILE *', 'NULL');
% Open file in binary mode
f = coder.ceval('fopen', cstring('filetest.m'), cstring('rb'));

% Read from file until end of file is reached and put
% contents into buffer
n = int32(1);
i = int32(1);
buffer = char(zeros(1,8192));
while n > 0
    % By default, MATLAB converts constant values
    % to doubles in generated code
    % so explicit type conversion to in32 is inserted.
    n = coder.ceval('fread', coder.ref(buffer(i)), int32(1), ...
        int32(numel(buffer)), f);
    i = i + n;
end
coder.ceval('fclose',f);

buffer = strip_cr(buffer);

% Put a C termination character '\0' at the end of MATLAB character vector
function y = cstring(x)
    y = [x char(0)];

% Remove character 13 (CR) but keep character 10 (LF)
function buffer = strip_cr(buffer)
j = 1;
for i = 1:numel(buffer)
    if buffer(i) ~= char(13)
        buffer(j) = buffer(i);
        j = j + 1;
    end
end
buffer(i) = 0;
Was this topic helpful?