Main Content

coder.ceval

Call external C/C++ function

Description

example

coder.ceval(cfun_name) executes the external C/C++ function specified by cfun_name. Define cfun_name in an external C/C++ source file or library. Provide the external source, library, and header files to the code generator.

example

coder.ceval(cfun_name,cfun_arguments) executes cfun_name with arguments cfun_arguments. cfun_arguments is a comma-separated list of input arguments in the order that cfun_name requires.

By default, coder.ceval passes arguments by value to the C/C++ function whenever C/C++ supports passing arguments by value. To make coder.ceval pass arguments by reference, use the constructs coder.ref, coder.rref, and coder.wref. If C/C++ does not support passing arguments by value, for example, if the argument is an array, coder.ceval passes arguments by reference. If you do not use coder.ref, coder.rref or coder.wref, a copy of the argument can appear in the generated code to enforce MATLAB® semantics for arrays.

example

coder.ceval('-global',cfun_name) executes cfun_name and indicates that cfun_name uses one or more MATLAB global variables. The code generator can then produce code that is consistent with this global variable usage.

Note

The -global flag is only supported for code generation. You cannot include this flag while calling coder.ceval in MATLAB Function blocks.

coder.ceval('-global',cfun_name,cfun_arguments) executes cfun_name with arguments cfun_arguments and indicates that cfun_name uses one or more MATLAB global variables.

coder.ceval('-gpudevicefcn',devicefun_name,devicefun_arguments) allows you to call CUDA® GPU __device__ functions from within kernels. '-gpudevicefcn' indicates to coder.ceval that the target function is on the GPU device. devicefun_name is the name of the __device__ function and devicefun_arguments is a comma-separated list of input arguments in the order that devicefun_name requires. This option requires the GPU Coder™ product.

example

coder.ceval('-layout:rowMajor',cfun_name,cfun_arguments) executes cfun_name with arguments cfun_arguments and passes data stored in row-major layout. When called from a function that uses column-major layout, the code generator converts inputs to row-major layout and converts outputs back to column-major layout. For a shorter syntax, use coder.ceval('-row',...).

coder.ceval('-layout:columnMajor',cfun_name,cfun_arguments) executes cfun_name with arguments cfun_arguments and passes data stored in column-major layout. When called from a function that uses row-major layout, the code generator converts inputs to column-major layout and converts outputs back to row-major layout. For a shorter syntax, use coder.ceval('-col',...).

coder.ceval('-layout:any',cfun_name,cfun_arguments) executes cfun_name with arguments cfun_arguments and passes data with its current array layout, even when array layouts do not match. The code generator does not convert the array layout of the input or output data.

example

cfun_return = coder.ceval(___) executes cfun_name and returns a single scalar value, cfun_return, corresponding to the value that the C/C++ function returns in the return statement. To be consistent with C/C++, coder.ceval can return only a scalar value. It cannot return an array. Use this option with any of the input argument combinations in the previous syntaxes.

Examples

collapse all

Call a C function foo(u) from a MATLAB function from which you intend to generate C code.

Create a C header file foo.h for a function foo that takes two input parameters of type double and returns a value of type double.

double foo(double in1, double in2);

Write the C function foo.c.

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

double foo(double in1, double in2)
{
  return in1 + in2;
}

Write a function callfoo that calls foo by using coder.ceval. Provide the source and header files to the code generator in the function.

function y = callfoo  %#codegen
y = 0.0;
if coder.target('MATLAB')
    % Executing in MATLAB, call MATLAB equivalent of
    % C function foo
    y = 10 + 20;
else
    % Executing in generated code, call C function foo
    coder.updateBuildInfo('addSourceFiles','foo.c');
    coder.cinclude('foo.h');
    y = coder.ceval('foo', 10, 20);
end
end

Generate C library code for function callfoo. The codegen function generates C code in the \codegen\lib\callfoo subfolder.

codegen -config:lib callfoo -report

Call a C library function from MATLAB code.

Write a MATLAB function myabsval.

function y = myabsval(u)   
%#codegen
y = abs(u);

Generate a C static library for myabsval, using the -args option to specify the size, type, and complexity of the input parameter.

codegen -config:lib myabsval -args {0.0}
The codegen function creates the library file myabsval.lib and header file myabsval.h in the folder \codegen\lib\myabsval. (The library file extension can change depending on your platform.) It generates the functions myabsval_initialize and myabsval_terminate in the same folder.

Write a MATLAB function to call the generated C library function using coder.ceval.

function y = callmyabsval(y)  
%#codegen
% Check the target. Do not use coder.ceval if callmyabsval is
% executing in MATLAB
if coder.target('MATLAB')
  % Executing in MATLAB, call function myabsval
  y = myabsval(y);
else
  % add the required include statements to generated function code
  coder.updateBuildInfo('addIncludePaths','$(START_DIR)\codegen\lib\myabsval');
  coder.cinclude('myabsval_initialize.h');
  coder.cinclude('myabsval.h');
  coder.cinclude('myabsval_terminate.h');

  % Executing in the generated code. 
  % Call the initialize function before calling the 
  % C function for the first time
  coder.ceval('myabsval_initialize');

  % Call the generated C library function myabsval
  y = coder.ceval('myabsval',y);
  
  % Call the terminate function after
  % calling the C function for the last time
  coder.ceval('myabsval_terminate');
end

Generate the MEX function callmyabsval_mex. Provide the generated library file at the command line.

codegen -config:mex callmyabsval codegen\lib\myabsval\myabsval.lib -args {-2.75}

Rather than providing the library at the command line, you can use coder.updateBuildInfo to specify the library within the function. Use this option to preconfigure the build. Add this line to the else block:

coder.updateBuildInfo('addLinkObjects','myabsval.lib','$(START_DIR)\codegen\lib\myabsval',100,true,true);

Note

The START_DIR macro is only supported for generating code with MATLAB Coder™.

Run the MEX function callmyabsval_mex which calls the library function myabsval.

callmyabsval_mex(-2.75)
ans =

    2.7500

Call the MATLAB function callmyabsval.

callmyabsval(-2.75)
ans =

    2.7500
The callmyabsval function exhibits the desired behavior for execution in MATLAB and in code generation.

Use the '-global' flag when you call a C function that modifies a global variable.

Write a MATLAB function useGlobal that calls a C function addGlobal. Use the '-global' flag to indicate to the code generator that the C function uses a global variable.

function y = useGlobal()
global g;
t = g;
% compare execution with/without '-global' flag
coder.ceval('-global','addGlobal'); 
y = t;
end

Create a C header file addGlobal.h for the function addGlobal.

void addGlobal(void);

Write the C function addGlobal in the file addGlobal.c. This function includes the header file useGlobal_data.h that the code generator creates when you generate code for the function useGlobal. This header file contains the global variable declaration for g.

#include "addGlobal.h"
#include "useGlobal_data.h"
void addGlobal(void) {
    g++;
}

Generate the MEX function for useGlobal. To define the input to the code generator, declare the global variable in the workspace.

global g;
g = 1;
codegen useGlobal -report addGlobal.h addGlobal.c
y = useGlobal_mex();

With the '-global' flag, the MEX function produces the result y = 1. The '-global' flag indicates to the code generator that the C function possibly modifies the global variable. For useGlobal, the code generator produces this code:

real_T useGlobal(const emlrtStack *sp)
{
  real_T y;
  (void)sp;
  y = g;
  addGlobal();
  return y;
}

Without the '-global' flag, the MEX function produces y = 2. Because there is no indication that the C function modifies g, the code generator assumes that y and g are identical. This C code is generated:

real_T useGlobal(const emlrtStack *sp)
{
  (void)sp;
  addGlobal();
  return g;
}

Suppose that you have a C function testRM that is designed to use row-major layout. You want to integrate this function into a MATLAB function bar that operates on arrays. The function bar is designed to use column-major layout, employing the coder.columnMajor directive.

function out = bar(in)
%#codegen
coder.columnMajor;
coder.ceval('-layout:rowMajor','testRM', ...
    coder.rref(in),coder.wref(out));
end

In the generated code, the code generator inserts a layout conversion from column-major layout to row-major layout on the variable in before passing it to testRM. On the output variable out, the code generator inserts a layout conversion back to column-major.

In general, if you do not specify the layout option for coder.ceval, the external function arguments are assumed to use column-major.

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 a struct that has two fields, re and im, 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 the codegen\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 the rtwtypes.h header file. An example C code foo.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.re*x.re + x.im*x.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 the coder.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 the struct 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 external C/C++ function to call.

Example: coder.ceval('foo')

Data Types: char | string

Comma-separated list of input arguments in the order that cfun_name requires.

Example: coder.ceval('foo', 10, 20);

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

Limitations

  • You cannot use coder.ceval on functions that you declare extrinsic with coder.extrinsic.

  • When the LCC compiler creates a library, it adds a leading underscore to the library function names. If the compiler for the library was LCC and your code generation compiler is not LCC, you must add the leading underscore to the function name, for example, coder.ceval('_mylibfun'). If the compiler for a library was not LCC, you cannot use LCC to generate code from MATLAB code that calls functions from that library. Those library function names do not have the leading underscore that the LCC compiler requires.

  • If a property has a get method, a set method, or validators, or is a System object™ property with certain attributes, then you cannot pass the property by reference to an external function. See Passing By Reference Not Supported for Some Properties.

  • Variable-size matrices as entry-point parameters are not supported for row-major code generation.

Tips

  • For code generation, before calling coder.ceval, you must specify the type, size, and complexity data type of return values and output arguments.

  • To apply coder.ceval to a function that accepts or returns variables that do not exist in MATLAB code, such as pointers, FILE types for file I/O, and C/C++ macros, use the coder.opaque function.

  • Use coder.ceval only in MATLAB for code generation. coder.ceval generates an error in uncompiled MATLAB code. To determine if a MATLAB function is executing in MATLAB, use coder.target. If the function is executing in MATLAB, call the MATLAB version of the C/C++ function.

  • External code called by using coder.ceval and the generated code run within the same process and share memory. If external code erroneously writes to the memory that contains data structures used by the generated code, it might cause the process to behave unexpectedly or crash. For example, if the external code attempts to write data to an array after its end point, the process might behave unexpectedly or crash.

  • MATLAB uses UTF-8 as its system encoding on Windows® platform. As a result, system calls made from within a generated MEX function accept and return UTF-8 encoded strings. By contrast, the code generated by MATLAB Coder encodes text data by using the encoding specified by the Windows locale. So, if your MATLAB entry-point function uses coder.ceval to call external C/C++ functions that assume a different system encoding, then the generated MEX function might produce garbled text. If this happens, you must update the external C/C++ functions to handle this situation.

Extended Capabilities

C/C++ Code Generation
Generate C and C++ code using MATLAB® Coder™.

GPU Code Generation
Generate CUDA® code for NVIDIA® GPUs using GPU Coder™.

Version History

Introduced in R2011a