coder.ceval - Call C/C++ function from generated code - MATLAB (original) (raw)

Call C/C++ function from generated code

Syntax

Description

out = coder.ceval([functionName](#d126e11222),[arg1,...,argN](#mw%5F93f30bac-1017-41ab-bbf1-a9583fde60e3)) calls the C/C++ function specified in functionName from the generated code. One or more input arguments can be passed to the called C/C++ function within the function call. The called C/C++ function can return a single scalar output. For example, to call the C standard functionisalnum with input myChar and outputisNum, use isnum = coder.ceval("isalnum",myChar).

Because the type of the output returned by the C/C++ function is not known by the code generator at code generation time, you must specify the type ofout (for example, by assigning it a dummy value) before the coder.ceval call. Variables to hold nonscalar output can be passed by reference to the called C/C++ function by using coder.ref or coder.wref.

To call C/C++ standard functions, you must specify the header file usingcoder.cinclude or the"-headerfile" argument to coder.ceval. To call custom C/C++ functions, in addition to specifying the header file, you must also specify the external source file or library using coder.updateBuildInfo.

The coder.ceval function can only be used in the generated code. Calls to coder.ceval in MATLAB® execution produce an error. To determine if a MATLAB function is executing in MATLAB, use coder.target.

example

out = coder.ceval([options](#mw%5F9cfafd1e-98a2-4ad3-91ef-2f9bd3ea8bfd),[functionName](#d126e11222),[arg1,...,argN](#mw%5F93f30bac-1017-41ab-bbf1-a9583fde60e3)) calls the C/C++ function specified in functionName from the generated code using the options specified in the options argument. For example, use "-headerfile" to specify a C/C++ header file, and use "-global" to indicate that the called C/C++ function uses global variables.

example

Examples

collapse all

Use coder.ceval to call the C standard library function cosh() from the generated code.

Create a MATLAB function callCosh that takes an input of type double, representing an angle in radians, and calculates the hyperbolic cosine of that angle using the C function cosh(). Call cosh() using coder.ceval and use coder.cinclude to include the math.h header file in which cosh() is defined. Enclose math.h in angle brackets <> to identify math.h as a C standard header file.

Because the type of the output returned by the coder.ceval call is unknown at code generation time, you must convert the output of the coder.ceval call to a known type by assigning the output to a variable whose type is already defined by prior assignment. Without this prior assignment, code generation fails.

Calls to coder.ceval in MATLAB execution produce an error. Use coder.target to make sure that callCosh is executing in the generated code before the call to coder.ceval.

function out = callCosh(x) arguments x (1,1) double end out = 0; % assign a dummy value to specify variable type if coder.target("MATLAB") disp("This function not supported in MATLAB execution"); else coder.cinclude("<math.h>") out = coder.ceval("cosh",x); end end

Test callCosh in MATLAB. callCosh does not call coder.ceval.

This function not supported in MATLAB execution

Generate a MEX function for callCosh.

Code generation successful.

Test the generated MEX function callCosh_mex using an angle of π radians. Because callCosh executes in the generated code, the call to coder.ceval does not error.

Generate C code for callCosh and inspect the generated code. The generated C function includes a call to cosh().

codegen -config:lib callCosh

Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because Embedded Coder is not installed, this might cause some Embedded Coder features to fail.

Code generation successful (with warnings): View report

type(fullfile("codegen","lib","callCosh","callCosh.c"))

/*

/* Include Files */ #include "callCosh.h" #include <math.h>

/* Function Definitions / /

/*

Call the C functions fopen(), fclose(), and fscanf() from the generated code using coder.ceval, and use these functions to read the first line of a text file containing comma-separated values. The MATLAB equivalents of these C functions, fopen, fclose, and fscanf, are supported for code generation. This example shows how to call C file I/O functions directly.

Create a MATLAB function useCFileIO that returns the first line of text file data.csv by using coder.ceval to call the C file I/O functions fopen(), fclose(), and fscanf(). Use coder.cinclude with angle brackets to include the C standard header file stdio.h, in which the C file I/O functions are defined, in the generated code. Use coder.opaque to initialize the variable that stores the file pointer as a variable with type FILE * and initial value NULL.

Because coder.ceval does not support array output, use coder.wref to pass the output variable out by reference to the C function fscanf(). Because the type of out is unknown at code generation time, initialize this variable using dummy values before the coder.ceval call. Without this assignment, code generation fails. To pass MATLAB character vectors to C/C++ functions called using coder.ceval, you must explicitly terminate each character vector with a null character (0). For more information, see Generate C/C++ Strings from MATLAB Strings and Character Row Vectors.

Calls to coder.ceval in MATLAB execution produce an error. Use coder.target to make sure that useCFileIO is executing in the generated code before the call to coder.ceval.

function out = useCFileIO %#codegen fileName = 'data.csv'; if coder.target("MATLAB") fid = fopen(fileName); out = fscanf(fid, "%f,%f,%f",3); fclose(fid); else coder.cinclude("<stdio.h>") fileName = [fileName 0]; fileMode = ['r' 0]; fileFormat = ['%lf,%lf,%lf' 0]; fileHandle = coder.opaque("FILE*", "NULL"); fileHandle = coder.ceval("fopen", fileName, fileMode); out = [0,0,0]; coder.ceval("fscanf", fileHandle, fileFormat, ... coder.wref(out), coder.wref(out(2)), coder.wref(out(3))); coder.ceval("fclose", fileHandle); end

Generate and test a MEX function for useCFileIO.

Code generation successful.

out = 1×3

0.7071    0.6690    0.5985

Generate C code for useCFileIO and inspect the generated code. The generated C function calls fopen(), fclose(), and fscanf() directly.

codegen -config:lib -c useCFileIO

Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because Embedded Coder is not installed, this might cause some Embedded Coder features to fail.

Code generation successful (with warnings): View report

type(fullfile("codegen","lib","useCFileIO","useCFileIO.c"))

/*

/* Include Files */ #include "useCFileIO.h" #include <stdio.h>

/* Function Definitions / /

/*

Call custom C function myAdd() from the MATLAB function addTwo.

Create a Custom C Function

Create the C header file myAdd.h. In this header file, declare the function myAdd(), which takes two input arguments of type double and returns a value of type double.

double myAdd(double a, double b);

Create a C function myAdd() that adds the two input arguments. Save the function in myAdd.c and include the header file myAdd.h.

#include <stdio.h> #include <stdlib.h> #include "myAdd.h"

double myAdd(double a, double b) { return a + b; }

Create a MATLAB Function That Calls the Custom C Function

Create the MATLAB function addTwo, which calls the custom C function myAdd() by using coder.ceval. Create a local MATLAB function myAddML that mimics the myAdd() C function. Use coder.target to make sure that addTwo calls the local MATLAB function myAddML when executing in MATLAB and calls the C function myAdd() when executing in the generated code. Use coder.updateBuildInfo to tell the compiler where to find the C file containing the myAdd() function, and use coder.ceval with the "-headerfile" option to instruct the code generator to include the myAdd.h header file.

function z = addTwo(x,y) %#codegen arguments x (1,1) double; y (1,1) double; end z = 0; if coder.target("MATLAB") % Executing in MATLAB, call local MATLAB function z = myAddML(x,y); else % Executing in generated code, call C function coder.updateBuildInfo("addSourceFiles","myAdd.c"); z = coder.ceval("-headerfile","myAdd.h","myAdd",x,y); end end

function out = myAddML(a,b) arguments a (1,1) double b (1,1) double end out = a + b; end

Generate and Test MEX Function

Generate a MEX function for addTwo, and make sure that the output of addTwo_mex matches that of addTwo for the same inputs.

Code generation successful.

Generate and Inspect C Code

Generate C code packaged as a standalone C library from addTwo at the command line using the codegen command with the -config:lib option. The generated C code includes a call to the myAdd() C function, as well as the directive #include "myAdd.h".

codegen -config:lib addTwo.m

Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because Embedded Coder is not installed, this might cause some Embedded Coder features to fail.

Code generation successful (with warnings): View report

type(fullfile("codegen","lib","addTwo","addTwo.c"))

/*

/* Include Files */ #include "addTwo.h" #include "myAdd.h"

/* Function Definitions / /

/*

In C++, a member function, also known as a method, is a function that is associated with a specific class or object. Call a public method of a custom C++ class MyClass from the generated code using coder.ceval.

Create Simple C++ Class

For the purposes of this example, create the C++ class MyClass in the file MyClass.hpp. In this header file, define the function getValue(), which returns a constant value.

class MyClass { public: double getValue() const { return 3.14; } };

Call Member Function from Generated Code

Create MATLAB function callGetValue, which calls the C++ member function getValue(). Use coder.opaque to declare the variable instanceOfMyClass as instance of the C++ class MyClass. Use the "HeaderFile" argument to indicate that MyClass is defined in the header file MyClass.hpp.

To call getValue() from the generated code using coder.ceval, use the C++ function template std:mem_fn to access getValue(). This function template is defined in the C++ standard header <functional>. Pass instanceOfMyClass to getValue() using coder.ref to force the code generator to pass this variable by reference instead of by value.

function out = callGetValue instanceOfMyClass = coder.opaque("MyClass", "MyClass{}", "HeaderFile", "MyClass.hpp"); out = 0; out = coder.ceval("-headerfile", "", ... "std::mem_fn(&MyClass::getValue)", coder.ref(instanceOfMyClass)); end

Generate and Test MEX Function

Generate a MEX function for callGetValue, and make sure that the MEX function produces the expected output. To generate a C++ MEX function, specify -lang:C++ in the codegen command.

codegen -lang:c++ callGetValue

Code generation successful.

Generate and Inspect C++ Code

Generate C++ code packaged as a standalone C++ library from callGetValue at the command line using the codegen command with the -config:lib and -lang:c++ options. The generated C++ code creates an instance of MyClass and calls the member function getValue().

codegen -config:lib -lang:c++ callGetValue

Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because Embedded Coder is not installed, this might cause some Embedded Coder features to fail.

Code generation successful (with warnings): View report

type(fullfile("codegen","lib","callGetValue","callGetValue.cpp"))

// // Prerelease License - for engineering feedback and testing purposes // only. Not for sale. // File: callGetValue.cpp // // MATLAB Coder version : 25.1 // C/C++ source code generated on : 01-Feb-2025 08:02:24 //

// Include Files #include "callGetValue.h" #include "MyClass.hpp" #include

// Function Definitions // // Arguments : void // Return Type : double // double callGetValue() { MyClass instanceOfMyClass; instanceOfMyClass = MyClass{}; return std::mem_fn(&MyClass::getValue)(&instanceOfMyClass); }

// // File trailer for callGetValue.cpp // // [EOF] //

You can use coder.ceval to call C/C++ functions that are defined in custom C/C++ libraries. These functions can have their own initialize and terminate functions.

Create Custom C Function and Library

For the purposes of this example, create a MATLAB function integrateSquare that calculates the definite integral of x2 over the interval [min, max]. Generate a standalone C library for integrateSquare.

function out = integrateSquare(min,max) arguments min (1,1) double max (1,1) double end f = @(x) x.^2; out = integral(f, min, max); end

codegen -config:lib integrateSquare

Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because Embedded Coder is not installed, this might cause some Embedded Coder features to fail.

Code generation successful (with warnings): View report

Inspect the generated C code, which is located in the directory codegen/lib/integrateSquare. The integrateSquare library and header files, as well as files containing definitions for the integrateSquare_initialize() and integrateSquare_terminate() functions, are located in the same directory.

type(fullfile("codegen","lib","integrateSquare","integrateSquare.c"))

/*

/* Include Files */ #include "integrateSquare.h" #include "integral.h" #include "rt_nonfinite.h"

/* Function Definitions / /

/*

Create MATLAB Function to Call Custom C Function

Create a MATLAB function callIntegrateSquare that calls the custom C function integrateSquare() using coder.ceval. For the purposes of this example, call the integrateSquare_initialize() function before the integrateSquare() call, and call the integrateSquare_terminate() function after.

Use coder.updateBuildInfo to add the directory containing the integrateSquare() library and other files to the include path. In the call to the coder.updateBuildInfo function, you can use the START_DIR macro to reference the current working folder. This macro can only be used in MATLAB code for code generation. Because MATLAB coder generates static library files with platform-specific extensions, use ispc to make sure that you use the correct extension for your platform.

type callIntegrateSquare.m

function out = callIntegrateSquare(x,y) %#codegen arguments x (1,1) double y (1,1) double end if coder.target("MATLAB") disp("Calling MATLAB function"); out = integrateSquare(x,y); else disp("Calling custom C function"); out = 0; coder.updateBuildInfo("addIncludePaths", ... "$(START_DIR)/codegen/lib/integrateSquare"); if ispc coder.updateBuildInfo("addLinkObjects","integrateSquare.lib", ... "$(START_DIR)/codegen/lib/integrateSquare","",true,true); else coder.updateBuildInfo("addLinkObjects","integrateSquare.a", ... "$(START_DIR)/codegen/lib/integrateSquare","",true,true); end
coder.ceval("-headerfile","integrateSquare_initialize.h", ... "integrateSquare_initialize"); out = coder.ceval("-headerfile","integrateSquare.h","integrateSquare", ... x,y); coder.ceval("-headerfile","integrateSquare_terminate.h", ... "integrateSquare_terminate"); end end

Generate and Test MEX Function

Generate a MEX function for callIntegrateSquare. Make sure that the MATLAB and MEX function results match.

codegen callIntegrateSquare

Code generation successful.

callIntegrateSquare(-2,2)

callIntegrateSquare_mex(-2,2)

Calling custom C function

Generate and Inspect C Code

Generate a standalone C library for callIntegrateSquare and inspect the call to integrateSquare_initialize(), integrateSquare(), and integrateSquare_terminate() in the generated code.

codegen -config:lib callIntegrateSquare

Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because Embedded Coder is not installed, this might cause some Embedded Coder features to fail.

Code generation successful (with warnings): View report

type(fullfile("codegen","lib","callIntegrateSquare","callIntegrateSquare.c"))

/*

/* Include Files */ #include "callIntegrateSquare.h" #include "coder_platform.h" #include "integrateSquare.h" #include "integrateSquare_initialize.h" #include "integrateSquare_terminate.h"

/* Function Definitions / /

/*

Suppose you have a MATLAB function that calls custom C code that takes complex number inputs. You must define your C code input parameters so that the complex number inputs from your MATLAB function can map to your C code.

In generated code, complex numbers are defined as astruct that has two fields, re andim, which are the real and imaginary part of a complex number respectively. This struct is defined in the header file rtwtypes.h, which you can find in thecodegen\lib\functionName folder of your current path. The struct is defined as follows:

typedef struct { real32_T re; /Real Component/ real32_T im; /Imaginary Component/ } creal_T;

For more information, see Mapping MATLAB Types to Types in Generated Code.

The C code that you want to integrate must include thertwtypes.h header file. An example C codefoo.c is shown below:

#include "foo.h" #include<stdio.h> #include<stdlib.h> #include "rtwtypes.h"

double foo(creal_T x) { double z = 0.0; z = x.rex.re + x.imx.im; return (z); }

The struct is named creal_T. A header file foo.h must also be defined as:

#include "rtwtypes.h" double foo(creal_T x);

The MATLAB code executes foo.c by using thecoder.ceval function that has a complex numbers input:

function y = complexCeval %#codegen y = 0.0; coder.updateBuildInfo("addSourceFiles","foo.c"); coder.cinclude("foo.h"); y = coder.ceval("foo", 10+20i); end

The coder.ceval command takes the complex number input. The code generator maps the complex number to thestruct creal_T variable x and its fields re and im.

Generate code for the function complexCeval by running this command:

codegen -config:lib -report complexCeval

Input Arguments

collapse all

Name of C/C++ function to be executed in the generated code, specified as a string scalar or character vector. functionName must be a constant at code generation time.

Example: x = coder.ceval("myFunction")

Example: coder.ceval("myFunction")

Data Types: char | string

Arguments to the called C/C++ function, specified as a comma-separated list of character vectors, arrays, elements of an array, structures, structure fields, or object properties, in the order required by the function. String scalars and string arrays are not supported.

By default, coder.ceval passes arguments by value to the called C/C++ function whenever C/C++ supports passing arguments by value. To force coder.ceval to pass arguments by reference, use the constructs coder.ref, coder.rref, and coder.wref. In situations where C/C++ does not support passing arguments by value, such as when the argument is an array, coder.ceval passes arguments by reference. If you do not use coder.ref,coder.rref or coder.wref, copies of C/C++ function arguments can appear in the generated code to enforce MATLAB semantics for arrays.

Example: x = coder.ceval("tolower",myChar)

Example: coder.ceval("myFunction",coder.ref(x))

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | logical | char | struct
Complex Number Support: Yes

Options for the C/C++ function call evaluated bycoder.ceval, specified as an option value or a comma-separated list of option values. Multiple options can be specified for the coder.ceval function, and options can appear in any order. All options (including_headerfile_) must be constants at code generation time. This table shows the options available for coder.ceval.

option Description
"-global" Specify that the C/C++ function to be called bycoder.ceval uses one or more global variables. The -global option inhibits certain code generation optimizations that can interfere with global variable use in the called C/C++ function.
"-gpudevicefcn" Specify that the C/C++ function to be called bycoder.ceval is located on a GPU device. This option allows you to call CUDA® GPU __device__ functions from within kernels. This option requires a GPU Coder™ license.
"-headerfile","headerfile" Specify that the C/C++ function to be called bycoder.ceval is declared in the header file_headerfile_. The code generator adds an#include statement for the specified header file in the generated code. You can use the "-headerfile" argument tocoder.ceval instead of a separate call to the coder.cinclude function. You can specify only one header file by using the"-headerfile" option.To include a C/C++ standard header file, enclose the name of the header file in angle brackets <>. The generated#include statement has the format #include <_headerfile_>. A standard header file must be in a standard location or on the include path.coder.ceval("-headerfile","<math.h>","atan",45)To include a nonstandard header file, omit the angle brackets. The generated #include statement has the format #include "headerfile". The nonstandard header file must be in the current folder or on the include path.coder.ceval("-headerfile","myHeader","myFun")To specify the include path, use addIncludePaths.
"-layout:any" Pass input and output data between the generated code and the called C/C++ function without changing the data layout, even when array layouts do not match.
"-layout:rowMajor" or"-row" Pass input and output data between the generated code and the called C/C++ function in a row-major layout. When called from a MATLAB function or a MATLAB Function block that uses the column-major layout, the code generator converts inputs to a row-major layout and converts outputs back to a column-major layout.
"-layout:columnMajor" or"-col" Pass input and output data between the generated code and the called C/C++ function in a column-major layout. When called from a MATLAB function or a MATLAB Function block that uses the row-major layout, the code generator converts inputs to a column-major layout and converts outputs back to a row-major layout. This behavior is the default.

Example: coder.ceval("-headerfile","myHeader.h","-layout:rowMajor","-global","myFunction",coder.rref(in),coder.wref(out));

Limitations

Tips

Extended Capabilities

expand all

The coder.ceval function support only MATLAB to High-Level Synthesis (HLS) workflow in HDL Coder™.

Version History

Introduced in R2011a

expand all

Starting in R2024a, you can specify a header file for a C/C++ function within acoder.ceval call by using the"-headerfile" name-value argument. Prior to R2024a, you had to specify a header file separately by calling coder.cinclude before coder.ceval.