coder.ceval
从生成的代码中调用 C/C++ 函数
语法
说明
out = coder.ceval(
从生成的代码中调用在 functionName
,arg1,...,argN
)functionName
中指定的 C/C++ 函数。可以在该函数调用中将一个或多个输入参量传递给调用的 C/C++ 函数。调用的 C/C++ 函数可以返回单个标量输出。例如,要使用输入 myChar
和输出 isNum
调用 C 标准函数 isalnum
,请使用 isnum = coder.ceval("isalnum",myChar)
。
由于代码生成器在生成代码时不知道 C/C++ 函数返回的输出类型,您必须在 coder.ceval
调用之前指定 out
的类型(例如,通过为其赋予虚拟值)。用于保留非标量输出的变量可以通过使用 coder.ref
(MATLAB Coder) 或 coder.wref
(MATLAB Coder) 按引用传递到被调用的 C/C++ 函数。
要调用 C/C++ 标准函数,您必须使用 coder.ceval
的 "-headerfile"
或 coder.cinclude
(MATLAB Coder) 参量指定头文件。要调用自定义 C/C++ 函数,除了指定头文件外,还必须使用 coder.updateBuildInfo
(MATLAB Coder) 指定外部源文件或库。
coder.ceval
函数只能在生成的代码中使用。在执行 MATLAB® 时调用 coder.ceval
会生成错误。要确定某个 MATLAB 函数是否正在 MATLAB 中执行,请使用 coder.target
(MATLAB Coder)。
out = coder.ceval(
使用在 options
,functionName
,arg1,...,argN
)options
参量中指定的选项从生成的代码中调用在 functionName
中指定的 C/C++ 函数。例如,使用 "-headerfile"
指定 C/C++ 头文件,使用 "-global"
指示调用的 C/C++ 函数使用全局变量。
示例
调用 C 标准库函数
使用 coder.ceval
从生成的代码中调用 C 标准库函数 cosh()
。
创建一个 MATLAB 函数 callCosh
,该函数接受类型为 double
的输入,以弧度表示角度,并使用 C 函数 cosh()
计算该角度的双曲余弦值。使用 coder.ceval
调用 cosh()
,并使用 coder.cinclude
来包含在其中定义 cosh()
的 math.h
头文件。将 math.h
用尖括号 <>
括起来,以将 math.h
识别为 C 标准头文件。
由于 coder.ceval
调用返回的输出类型在代码生成时未知,因此您必须将 coder.ceval
调用的输出转换为已知类型,方法是将输出赋给一个其类型已由之前的赋值定义的变量。如果没有这种事先赋值,代码生成将失败。
在 MATLAB 执行中调用 coder.ceval
会生成错误。使用 coder.target
(MATLAB Coder) 确保在调用 coder.ceval
之前 callCosh
正在生成的代码中执行。
type callCosh.m
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
在 MATLAB 中测试 callCosh
。callCosh
不调用 coder.ceval
。
x = callCosh(1);
This function not supported in MATLAB execution
为 callCosh
生成一个 MEX 函数。
codegen callCosh
Code generation successful.
使用 弧度的角度测试生成的 MEX 函数 callCosh_mex
。由于 callCosh
在生成的代码中执行,因此对 coder.ceval
的调用不会发生错误。
callCosh_mex(pi)
ans = 11.5920
为 callCosh
生成 C 代码并检查生成的代码。生成的 C 函数包含对 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): To view the report, open('codegen/lib/callCosh/html/report.mldatx')
type(fullfile("codegen","lib","callCosh","callCosh.c"))
/* * File: callCosh.c * * MATLAB Coder version : 24.1 * C/C++ source code generated on : 12-Feb-2024 20:57:41 */ /* Include Files */ #include "callCosh.h" #include <math.h> /* Function Definitions */ /* * Arguments : double x * Return Type : double */ double callCosh(double x) { /* assign a dummy value to specify variable type */ return cosh(x); } /* * File trailer for callCosh.c * * [EOF] */
调用 C 文件输入/输出函数
使用 coder.ceval
从生成的代码中调用 C 函数 fopen()
、fclose()
和 fscanf()
,并使用这些函数读取包含逗号分隔值的文本文件的第一行。代码生成支持这些 C 函数的 MATLAB 等效函数 fopen
、fclose
和 fscanf
。此示例说明如何直接调用 C 文件 I/O 函数。
创建一个 MATLAB 函数 useCFileIO
,该函数通过使用 coder.ceval
调用 C 文件 I/O 函数 fopen()
、fclose()
和 fscanf()
来返回文本文件 data.csv
的第一行。使用 coder.cinclude
与尖括号以在生成的代码中包含 C 标准头文件 stdio.h
,该文件定义了 C 文件 I/O 函数。使用 coder.opaque
(MATLAB Coder) 将存储文件指针的变量初始化为类型为 FILE *
、初始值为 NULL
的变量。
由于 coder.ceval
不支持数组输出,因此请使用 coder.wref
通过引用 C 函数 fscanf()
来传递输出变量 out
。由于在代码生成时 out
的类型未知,因此请在 coder.ceval
调用之前使用虚拟值初始化此变量。如果没有此赋值,代码生成将失败。要将 MATLAB 字符向量传递给使用 coder.ceval
调用的 C/C++ 函数,必须用空字符 (0
) 显式终止每个字符向量。有关详细信息,请参阅Generate C/C++ Strings from MATLAB Strings and Character Row Vectors (MATLAB Coder)。
在 MATLAB 执行中调用 coder.ceval
会生成错误。使用 coder.target
确保在调用 coder.ceval
之前 useCFileIO
正在生成的代码中执行。
type useCFileIO.m
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
为 useCFileIO
生成并测试 MEX 函数。
codegen useCFileIO
Code generation successful.
out = useCFileIO_mex
out = 1×3
0.7071 0.6690 0.5985
为 useCFileIO
生成 C 代码并检查生成的代码。生成的 C 函数直接调用 fopen()
、fclose()
和 fscanf()
。
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): To view the report, open('codegen/lib/useCFileIO/html/report.mldatx')
type(fullfile("codegen","lib","useCFileIO","useCFileIO.c"))
/* * File: useCFileIO.c * * MATLAB Coder version : 24.1 * C/C++ source code generated on : 12-Feb-2024 20:57:33 */ /* Include Files */ #include "useCFileIO.h" #include <stdio.h> /* Function Definitions */ /* * Arguments : double out[3] * Return Type : void */ void useCFileIO(double out[3]) { static const char b_fileFormat[12] = "%lf,%lf,%lf"; static const char b_fileName[9] = "data.csv"; FILE *fileHandle; int i; char fileFormat[12]; char fileName[9]; for (i = 0; i < 9; i++) { fileName[i] = b_fileName[i]; } char fileMode[2]; fileMode[0] = 'r'; fileMode[1] = '\x00'; fileHandle = fopen(&fileName[0], &fileMode[0]); out[0] = 0.0; out[1] = 0.0; out[2] = 0.0; for (i = 0; i < 12; i++) { fileFormat[i] = b_fileFormat[i]; } fscanf(fileHandle, &fileFormat[0], &out[0], &out[1], &out[2]); fclose(fileHandle); } /* * File trailer for useCFileIO.c * * [EOF] */
调用自定义 C 函数
从 MATLAB 函数 addTwo
中调用自定义 C 函数 myAdd()
。
创建自定义 C 函数
创建 C 头文件 myAdd.h
。在此头文件中,声明函数 myAdd()
,此函数接受类型为 double
的两个输入参量,并返回类型为 double
的值。
type myAdd.h
double myAdd(double a, double b);
创建一个将两个输入参量相加的 C 函数 myAdd()
。将该函数保存在 myAdd.c
中,并包含头文件 myAdd.h
。
type myAdd.c
#include <stdio.h> #include <stdlib.h> #include "myAdd.h" double myAdd(double a, double b) { return a + b; }
创建调用自定义 C 函数的 MATLAB 函数
创建 MATLAB 函数 addTwo
,该函数使用 coder.ceval
调用自定义 C 函数 myAdd()
。创建一个模拟 myAdd()
C 函数的局部 MATLAB 函数 myAddML
。使用 coder.target
(MATLAB Coder) 确保 addTwo
在 MATLAB 中执行时调用局部 MATLAB 函数 myAddML
,在生成的代码中执行时调用 C 函数 myAdd()
。使用 coder.updateBuildInfo
(MATLAB Coder) 告知编译器在哪里可以找到包含 myAdd()
函数的 C 文件,并使用 coder.ceval
和 "-headerfile"
选项指示代码生成器包含 myAdd.h
头文件。
type addTwo.m
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
生成并测试 MEX 函数
为 addTwo
生成 MEX 函数,并确保对于相同的输入,addTwo_mex
的输出与 addTwo
的输出匹配。
codegen addTwo
Code generation successful.
addTwo(4,5)
ans = 9
addTwo_mex(4,5)
ans = 9
生成和检查 C 代码
使用带 -config:lib
选项的 codegen
命令在命令行中从 addTwo
生成打包为独立 C 库的 C 代码。生成的 C 代码包括对 myAdd()
C 函数的调用以及对 #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): To view the report, open('codegen/lib/addTwo/html/report.mldatx')
type(fullfile("codegen","lib","addTwo","addTwo.c"))
/* * File: addTwo.c * * MATLAB Coder version : 24.1 * C/C++ source code generated on : 12-Feb-2024 20:58:09 */ /* Include Files */ #include "addTwo.h" #include "myAdd.h" /* Function Definitions */ /* * Arguments : double x * double y * Return Type : double */ double addTwo(double x, double y) { /* Executing in generated code, call C function */ return myAdd(x, y); } /* * File trailer for addTwo.c * * [EOF] */
调用 C++ 成员函数
在 C++ 中,成员函数(亦称方法)是与特定类或对象相关联的函数。使用 coder.ceval
从生成的代码中调用自定义 C++ 类 MyClass
的公共方法。
创建简单的 C++ 类
出于此示例的目的,需要在文件 MyClass.hpp
中创建 C++ 类 MyClass
。在此头文件中,定义函数 getValue()
,该函数返回常量值。
type MyClass.hpp
class MyClass { public: double getValue() const { return 3.14; } };
从生成的代码中调用成员函数
创建 MATLAB 函数 callGetValue
,该函数调用 C++ 成员函数 getValue()
。使用 coder.opaque
(MATLAB Coder) 将变量 instanceOfMyClass
声明为 C++ 类 MyClass
的实例。使用 "HeaderFile"
参量指示 MyClass
是在头文件 MyClass.hpp
中定义的。
要使用 coder.ceval
从生成的代码中调用 getValue()
,请使用 C++ 函数模板 std:mem_fn
来访问 getValue()
。此函数模板在 C++ 标准头文件 <functional>
中定义。使用 coder.ref 将 instanceOfMyClass
传递给 getValue()
,以强制代码生成器按引用而不是按值来传递此变量。
type callGetValue.m
function out = callGetValue instanceOfMyClass = coder.opaque("MyClass", "MyClass{}", "HeaderFile", "MyClass.hpp"); out = 0; out = coder.ceval("-headerfile", "<functional>", ... "std::mem_fn(&MyClass::getValue)", coder.ref(instanceOfMyClass)); end
生成并测试 MEX 函数
为 callGetValue
生成一个 MEX 函数,并确保该 MEX 函数产生预期的输出。要生成 C++ MEX 函数,请在 codegen 命令中指定 -lang:C++
。
codegen -lang:c++ callGetValue
Code generation successful.
callGetValue_mex
ans = 3.1400
生成和检查 C++ 代码
使用具有 -config:lib
和 -lang:c++
选项的 codegen
命令在命令行中从 callGetValue
生成打包为独立 C++ 库的 C++ 代码。生成的 C++ 代码会创建一个 MyClass
实例,并调用成员函数 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): To view the report, open('codegen/lib/callGetValue/html/report.mldatx')
type(fullfile("codegen","lib","callGetValue","callGetValue.cpp"))
// // File: callGetValue.cpp // // MATLAB Coder version : 24.1 // C/C++ source code generated on : 12-Feb-2024 20:58:16 // // Include Files #include "callGetValue.h" #include "MyClass.hpp" #include <functional> // 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] //
调用自定义 C 库函数
您可以使用 coder.ceval
来调用在自定义 C/C++ 库中定义的 C/C++ 函数。这些函数可以有自己的初始化和终止函数。
创建自定义 C 函数和库
出于此示例的目的,需要创建一个 MATLAB 函数 integrateSquare
,用于计算区间 [min
, max]
上 的定积分。为 integrateSquare
生成独立的 C 库。
type integrateSquare.m
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): To view the report, open('codegen/lib/integrateSquare/html/report.mldatx')
检查生成的 C 代码,该代码位于目录 codegen/lib/integrateSquare
中。integrateSquare
库和头文件以及包含 integrateSquare_initialize()
和 integrateSquare_terminate()
函数定义的文件位于同一目录中。
type(fullfile("codegen","lib","integrateSquare","integrateSquare.c"))
/* * File: integrateSquare.c * * MATLAB Coder version : 24.1 * C/C++ source code generated on : 12-Feb-2024 20:57:46 */ /* Include Files */ #include "integrateSquare.h" #include "integralCalc.h" #include "integrateSquare_emxutil.h" #include "integrateSquare_types.h" #include "rt_nonfinite.h" #include "rt_nonfinite.h" #include <math.h> /* Function Definitions */ /* * Arguments : double b_min * double b_max * Return Type : double */ double integrateSquare(double b_min, double b_max) { emxArray_real_T *interval; double A; double B; double delta; double out; double *interval_data; int MaxIntervalCount; int i; int nx; int y; signed char problemType; boolean_T guard1; boolean_T isinfA; boolean_T isinfB; boolean_T reversedir; MaxIntervalCount = 16384; emxInit_real_T(&interval); i = interval->size[0] * interval->size[1]; interval->size[0] = 1; interval->size[1] = 2; emxEnsureCapacity_real_T(interval, i); interval_data = interval->data; if (b_max < b_min) { A = b_max; B = b_min; reversedir = true; } else { A = b_min; B = b_max; reversedir = false; } interval_data[0] = A; interval_data[1] = B; isinfA = rtIsInf(A); isinfB = rtIsInf(B); if (A == B) { problemType = 0; } else if (isinfA || isinfB) { if ((!isinfA) && isinfB) { interval_data[0] = 0.0; interval_data[1] = 1.0; problemType = 2; } else if (isinfA && (!isinfB)) { interval_data[0] = -1.0; interval_data[1] = 0.0; problemType = 3; } else if (isinfA && isinfB) { interval_data[0] = -1.0; interval_data[1] = 1.0; problemType = 4; } else { problemType = 0; } } else { interval_data[0] = -1.0; interval_data[1] = 1.0; problemType = 1; } i = interval->size[0] * interval->size[1]; interval->size[0] = 1; interval->size[1] = 2; emxEnsureCapacity_real_T(interval, i); interval_data = interval->data; guard1 = false; if (problemType == 0) { guard1 = true; } else { double pathlen_tmp; int n_data; int nt; nx = 2; pathlen_tmp = interval_data[1] - interval_data[0]; if (pathlen_tmp > 0.0) { n_data = (int)(ceil(pathlen_tmp * (10.0 / pathlen_tmp)) - 1.0); if (n_data <= 0) { y = 0; } else { y = n_data; } nt = y + 2; if (y >= 0) { nx = y; } else { nx = 0; } i = interval->size[0] * interval->size[1]; interval->size[1] = nx + 2; emxEnsureCapacity_real_T(interval, i); interval_data = interval->data; for (i = 0; i < nx; i++) { interval_data[i + 2] = 0.0; } if (y + 2 > 2) { interval_data[y + 1] = interval_data[1]; delta = (interval_data[1] - interval_data[0]) / (double)(n_data + 1); for (nx = n_data; nx >= 1; nx--) { interval_data[(y + nx) - n_data] = interval_data[0] + (double)nx * delta; } } nx = y + 2; } else { nt = 2; } n_data = 0; for (y = 2; y <= nx; y++) { delta = interval_data[y - 1]; if (fabs(delta - interval_data[n_data]) > 0.0) { n_data++; interval_data[n_data] = delta; } else { nt--; } } if (nt < 2) { double b_interval; delta = interval_data[0]; b_interval = interval_data[0]; i = interval->size[0] * interval->size[1]; interval->size[0] = 1; interval->size[1] = 2; emxEnsureCapacity_real_T(interval, i); interval_data = interval->data; interval_data[0] = delta; interval_data[1] = b_interval; nt = 2; } else { i = interval->size[0] * interval->size[1]; interval->size[1] = nt; emxEnsureCapacity_real_T(interval, i); } nx = (nt - 1) << 1; if (nx > 16384) { MaxIntervalCount = nx; } if (!(pathlen_tmp > 0.0)) { guard1 = true; } else { out = scalarValuedIntegral(A, B, interval, nt, pathlen_tmp, problemType, MaxIntervalCount, &delta, &isinfA); } } if (guard1) { delta = (b_min + b_max) / 2.0; if ((!rtIsInf(b_min)) && (!rtIsNaN(b_min)) && ((!rtIsInf(b_max)) && (!rtIsNaN(b_max))) && (rtIsInf(delta) || rtIsNaN(delta))) { delta = b_min / 2.0 + b_max / 2.0; } out = (b_max - b_min) * (delta * delta); } emxFree_real_T(&interval); if (reversedir) { out = -out; } return out; } /* * File trailer for integrateSquare.c * * [EOF] */
创建 MATLAB 函数来调用自定义 C 函数
创建一个使用 coder.ceval
调用自定义 C 函数 integrateSquare()
的 MATLAB 函数 callIntegrateSquare
。出于此示例的目的,需要在调用 integrateSquare()
之前调用 integrateSquare_initialize()
函数,然后再调用 integrateSquare_terminate()
函数。
使用 coder.updateBuildInfo
(MATLAB Coder) 将包含 integrateSquare()
库和其他文件的目录添加到包含路径中。在对 coder.updateBuildInfo
函数的调用中,您可以使用 START_DIR
宏来引用当前工作文件夹。此宏只能在 MATLAB 代码中用于代码生成。由于 MATLAB 代码生成器生成具有特定于平台的扩展名的静态库文件,请使用 ispc
来确保您使用适合您平台的正确扩展名。
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
生成并测试 MEX 函数
为 callIntegrateSquare
生成一个 MEX 函数。确保 MATLAB 和 MEX 函数结果匹配。
codegen callIntegrateSquare
Code generation successful.
callIntegrateSquare(-2,2)
Calling MATLAB function
ans = 5.3333
callIntegrateSquare_mex(-2,2)
Calling custom C function
ans = 5.3333
生成和检查 C 代码
为 callIntegrateSquare
生成独立的 C 库,并检查生成的代码中对 integrateSquare_initialize()
、integrateSquare()
和 integrateSquare_terminate()
的调用。
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): To view the report, open('codegen/lib/callIntegrateSquare/html/report.mldatx')
type(fullfile("codegen","lib","callIntegrateSquare","callIntegrateSquare.c"))
/* * File: callIntegrateSquare.c * * MATLAB Coder version : 24.1 * C/C++ source code generated on : 12-Feb-2024 20:58:01 */ /* Include Files */ #include "callIntegrateSquare.h" #include "coder_platform.h" #include "integrateSquare.h" #include "integrateSquare_initialize.h" #include "integrateSquare_terminate.h" #include <stdio.h> /* Function Definitions */ /* * Arguments : double x * double y * Return Type : double */ double callIntegrateSquare(double x, double y) { double out; printf("%s\n", "Calling custom C function"); fflush(stdout); coderIsPC(); integrateSquare_initialize(); out = integrateSquare(x, y); integrateSquare_terminate(); return out; } /* * File trailer for callIntegrateSquare.c * * [EOF] */
调用接受复数输入的 C 函数
假设您有一个调用自定义 C 代码的 MATLAB 函数,该函数接受复数输入。您必须定义您的 C 代码输入参数,以便来自 MATLAB 函数的复数输入可以映射到您的 C 代码。
在生成代码中,复数定义为 struct
,它有两个字段 re
和 im
,分别是复数的实部和虚部。此 struct
是在头文件 rtwtypes.h
中定义的,您可以在当前路径的 codegen\lib\functionName
文件夹中找到此头文件。struct
的定义如下:
typedef struct { real32_T re; /*Real Component*/ real32_T im; /*Imaginary Component*/ } creal_T;
有关详细信息,请参阅 将 MATLAB 类型映射到生成的代码中的类型 (MATLAB Coder)。
要集成的 C 代码必须包含 rtwtypes.h
头文件。C 代码示例 foo.c
如下所示:
#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); }
struct
命名为 creal_T
。头文件 foo.h
也必须定义为:
#include "rtwtypes.h" double foo(creal_T x);
MATLAB 代码通过使用具有复数输入的 coder.ceval
函数来执行 foo.c
:
function y = complexCeval %#codegen y = 0.0; coder.updateBuildInfo("addSourceFiles","foo.c"); coder.cinclude("foo.h"); y = coder.ceval("foo", 10+20i); end
coder.ceval
命令接受复数输入。代码生成器将复数映射到 struct creal_T
变量 x
及其字段 re
和 im
。通过运行以下命令,为函数 complexCeval
生成代码:
codegen -config:lib -report complexCeval
输入参数
functionName
— C/C++ 函数的名称
字符串标量 | 字符向量
要在生成的代码中执行的 C/C++ 函数的名称,指定为字符串标量或字符向量。functionName
在生成代码时必须为常量。
示例: x = coder.ceval("myFunction")
示例: coder.ceval("myFunction")
数据类型: char
| string
arg1,...,argN
— 调用的 C/C++ 函数的参量
逗号分隔的列表
调用的 C/C++ 函数的参量,指定为按照函数要求的顺序排列的、以逗号分隔的字符向量、数组、数组元素、结构体、结构体字段或对象属性列表。不支持字符串标量和字符串数组。
默认情况下,只要调用的 C/C++ 支持按值传递参量,coder.ceval
就会按值将参量传递给被调用的 C/C++ 函数。要强制 coder.ceval
按引用传递参量,请使用构造 coder.ref
(MATLAB Coder)、coder.rref
(MATLAB Coder) 和 coder.wref
(MATLAB Coder)。在 C/C++ 不支持按值传递参量的情况下,例如当参量为数组时,coder.ceval
按引用传递参量。如果不使用 coder.ref
、coder.rref
或 coder.wref
,C/C++ 函数参量的副本可以出现在生成的代码中,以强制执行数组的 MATLAB 语义。
示例: x = coder.ceval("tolower",myChar)
示例: coder.ceval("myFunction",coder.ref(x))
数据类型: single
| double
| int8
| int16
| int32
| int64
| uint8
| uint16
| uint32
| uint64
| logical
| char
| struct
复数支持: 是
options
— C/C++ 函数调用的选项
选项值 | 选项值的以逗号分隔的列表
由 coder.ceval
计算的 C/C++ 函数调用的选项,指定为选项值或以逗号分隔的选项值列表。可以为 coder.ceval
函数指定多个选项,并且这些选项可以按任意顺序排列。所有选项(包括 headerfile
)在代码生成时都必须为常量。下表显示对 coder.ceval
可用的选项。
选项 | 描述 |
---|---|
"-global" | 指定由 coder.ceval 调用的 C/C++ 函数使用一个或多个全局变量。-global 选项会禁止某些代码生成优化,因为这些优化可能会干扰调用的 C/C++ 函数中全局变量的使用。 |
"-gpudevicefcn" | 指定由 coder.ceval 调用的 C/C++ 函数位于 GPU 设备上。此选项允许您从内核中调用 CUDA® GPU __device__ 函数。此选项需要 GPU Coder™ 许可证。 |
"-headerfile","headerfile" | 指定由 要包含 C/C++ 标准头文件,请将头文件的名称用尖括号
要包含非标准头文件,请省略尖括号。生成的
要指定包含路径,请使用 |
"-layout:any" | 在生成的代码和调用的 C/C++ 函数之间传递输入和输出数据而无需更改数据布局,即使数组布局不匹配也是如此。这是默认行为。 |
"-layout:rowMajor" 或 "-row" | 在行优先布局中,在生成的代码和调用的 C/C++ 函数之间传递输入和输出数据。从使用列优先布局的 MATLAB 函数或 MATLAB Function 模块调用时,代码生成器会将输入转换为行优先布局,并将输出转换回列优先布局。 |
"-layout:columnMajor" 或 "-col" | 在列优先布局中,在生成的代码和调用的 C/C++ 函数之间传递输入和输出数据。从使用行优先布局的 MATLAB 函数或 MATLAB Function 模块调用时,代码生成器会将输入转换为列优先布局,并将输出转换回行优先布局。 |
示例: coder.ceval("-headerfile","myHeader.h","-layout:rowMajor","-global","myFunction",coder.rref(in),coder.wref(out));
限制
对于您使用
coder.ceval
声明为外部函数的函数,不能使用coder.extrinsic
(MATLAB Coder)。如果一个属性具有 get 方法、set 方法或验证器,或该属性是具有约束或修改属性值的特性的 System object™ 属性,则您无法通过引用外部函数来传递该属性。请参阅Passing By Reference Not Supported for Some Properties。
行优先代码生成不支持将可变大小矩阵作为入口函数参数。
提示
要使用
coder.ceval
调用接受或返回 MATLAB 代码中不存在变量类型的 C/C++ 函数,如指针、用于文件 I/O 和 C/C++ 宏的FILE
类型,请使用coder.opaque
函数。使用
coder.ceval
调用的外部代码和生成的代码在同一个进程中运行,并共享内存。如果外部代码错误地写入包含生成的代码使用的数据结构体的内存,则可能导致意外行为或崩溃。例如,如果外部代码尝试在其终点后将数据写入数组,生成的代码可能会出现意外行为或崩溃。MATLAB 在 Windows® 平台上使用 UTF-8 作为其系统编码。因此,从生成的 MEX 函数中进行的系统调用接受并返回 UTF-8 编码的字符串。相反,由 MATLAB Coder™ 生成的代码使用 Windows 区域设置指定的编码对文本数据进行编码。因此,如果您的 MATLAB 入口函数使用
coder.ceval
(MATLAB Coder) 来调用接受不同系统编码的外部 C/C++ 函数,则生成的 MEX 函数可能会产生乱码文本。如果发生这种情况,您必须更新外部 C/C++ 函数。
扩展功能
C/C++ 代码生成
使用 MATLAB® Coder™ 生成 C 代码和 C++ 代码。
GPU 代码生成
使用 GPU Coder™ 为 NVIDIA® GPU 生成 CUDA® 代码。
HDL 代码生成
使用 HDL Coder™ 为 FPGA 和 ASIC 设计生成 VHDL、Verilog 和 SystemVerilog 代码。
coder.ceval
函数仅支持 HDL Coder™ 中的 MATLAB 到高级综合 (HLS) 工作流。
版本历史记录
在 R2011a 中推出
MATLAB 命令
您点击的链接对应于以下 MATLAB 命令:
请在 MATLAB 命令行窗口中直接输入以执行命令。Web 浏览器不支持 MATLAB 命令。
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list:
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)