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.
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.
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.
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:
coder.ref
—
pass value by reference.
coder.rref
—
pass read-only value by reference.
coder.wref
—
pass write-only value by reference.
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)));
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
.
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;