主要内容

调用MATLAB编译器SDKC/ c++中的API函数

共享图书馆功能

生成的C或c++共享库MATLAB®编译器SDK™至少包含7个函数。生成了三个函数来管理库的初始化和终止,每个函数分别用于打印输出和错误消息,库中包含的每个MATLAB函数都有两个生成函数。

要生成本节中描述的函数,首先复制文件夹matlabroot\走读生\ \ compilersdk \ c_cpp例子\三角形到当前工作目录。

创建名为libtriangle它包含了函数sierpinski.m按照中的步骤用MATLAB代码创建一个C共享库生成一个c++ mwArray API共享库并构建一个c++应用程序,或生成一个c++ MATLAB数据API共享库并构建一个c++应用程序,这取决于所需的目标应用程序。

申请类别

创建共享库后,执行mbuild与目标语言对应的命令。该命令使用C/ c++编译器编译代码并将驱动程序代码链接到MATLAB编译器SDK生成C/ c++共享库。

对于C应用程序,使用Mbuild triangle.c libtriangle.lib

对于c++mwArrayAPI应用,使用Mbuild triangle_mwarray.cpp libtriangle.lib

对于c++ MATLAB Data API应用程序,使用mbuild triangle_mda.cpp

请注意

. lib扩展是Windows的®.在Mac,则文件扩展名为. dylib,以及在UNIX上®它是所以

这个命令假设C/ c++共享库、驱动程序代码和相应的头文件都在当前工作文件夹中。

中调用函数的所选源代码文件命名的主程序libtriangle共享库。标准库导出一个函数(包含在sierpinski.m),它使用简单的迭代算法来生成被称为谢尔宾斯基三角形的分形。主程序可以选择使用单个数值参数,该参数指定用于生成分形的点的数量。例如,三角形8000生成一个包含8000个点的图表。

调用共享库的程序结构

所有调用MATLAB编译器SDK生成的共享库具有大致相同的结构:

  1. 声明变量并处理/验证输入参数。

  2. 调用mclInitializeApplication并测试是否成功。这个函数设置全局变量MATLAB运行时状态并使构造成为可能MATLAB运行时实例。

  3. 调用<图书馆>初始化(WithHandlers)为每个库创建一次MATLAB运行时库所需的实例。

  4. 调用库中的函数并在程序主体中处理结果。

  5. 调用<图书馆>终止对每个库进行一次关联销毁MATLAB运行时

  6. 调用mclTerminateApplication释放与全局关联的资源MATLAB运行时状态。

  7. 清理变量,关闭文件等,然后退出。

库初始化和终止函数

库初始化函数和终止函数分别创建和销毁MATLAB运行时共享库所需的实例。必须在调用共享库中的任何其他函数之前调用初始化函数,并且应该在完成对共享库的调用之后调用终止函数,否则可能会导致内存泄漏。

初始化函数有两种形式<图书馆>初始化(WithHandlers)这是终结函数之一<图书馆>终止.生成的C/ c++共享库的名称用作函数名的一部分。两个初始化函数中较简单的一个不带参数;很有可能,这就是应用程序将调用的版本。在本例中,将调用这种形式的初始化函数libtriangleInitialize

bool libtriangleInitialize(空白)

此函数创建MATLAB运行时实例使用默认的打印和错误处理程序,以及在编译过程中生成的其他信息。

但是,如果希望更多地控制打印输出和错误消息的处理方式,可以调用该函数的第二种形式,它带有两个参数。在本例中,将调用这种形式的初始化函数libtriangleInitializeWithHandlers

bool libtriangleInitializeWithHandlers(mclOutputHandlerFcn error_handler, mclOutputHandlerFcn print_handler)

类调用的打印和错误处理例程,可以提供自己的版本MATLAB运行时.这些例程中的每一个都具有相同的签名(有关完整的详细信息,请参见打印和错误处理功能).通过覆盖默认值,您可以控制如何显示输出,例如,是否将输出放入日志文件。

请注意

在调用任何一种形式的库初始化例程之前,必须首先调用mclInitializeApplication设置全局MATLAB运行时状态。有关更多信息,请参见调用一个C共享库

在微软®Windows平台上,MATLAB编译器SDK生成一个额外的初始化函数:标准的Microsoft DLL初始化函数开始时

BOOL WINAPI DllMain(HINSTANCE HINSTANCE, DWORD dwReason, void *pv)

生成的开始时执行非常重要的服务;它定位共享库存储在磁盘上的目录。此信息用于查找可部署存档,没有该存档应用程序将无法运行。如果修改生成的开始时(不推荐),请确保保留这部分功能。

库终止很简单。

空白libtriangleTerminate(空白)

在调用之前调用此函数(每个库一次)mclTerminateApplication

打印和错误处理功能

默认情况下,MATLAB编译器SDK生成的应用程序和共享库将打印输出发送到标准输出,将错误消息发送到标准错误。MATLAB编译器SDK生成实现此策略的默认打印处理程序和默认错误处理程序。如果您想要改变这种行为,您必须编写自己的错误和打印处理程序,并将它们传递给相应的生成初始化函数。

你可以替换这两个函数中的一个,两个,或者两个都不替换。的MATLAB运行时通过打印处理程序发送所有常规输出,并通过错误处理程序发送所有错误输出。因此,如果重新定义其中一个函数,则MATLAB运行时将对属于它调用该处理程序的类的所有输出使用您的函数版本。

默认的打印处理程序采用以下形式。

mclDefaultPrintHandler(const char *s)

实现很简单;它接受一个字符串,将其打印到标准输出中,并返回打印的字符数。如果重写或替换此函数,则您的版本还必须接受一个字符串并返回“处理”的字符数。的MATLAB运行时当一个正在执行的MATLAB文件请求打印输出时,例如通过MATLAB函数调用打印处理程序disp.打印处理程序不会用回车符或换行符结束输出。

默认错误处理程序具有与打印处理程序相同的表单。

mclDefaultErrorHandler(const char *s)

但是,打印处理程序的默认实现略有不同。它将输出发送到标准错误输出流,但如果字符串不以回车符结束,错误处理程序将添加一个回车符。类打印的错误消息中,如果用自己的错误处理程序替换默认的错误处理程序,也应该执行此检查MATLAB运行时将无法正确格式化。

有关在应用程序中使用自定义打印和错误处理函数的示例,请参阅matlabroot\走读生\ \ compilersdk \ c_cpp \ catcherror例子

谨慎

错误处理程序并不处理实际的错误,而是处理在捕获和处理错误后产生的消息MATLAB运行时.类的错误处理行为,不能使用此函数修改MATLAB运行时——使用试一试而且语句,如果你想控制aMATLAB编译器SDK生成的应用程序响应错误条件。

请注意

如果您提供了任意一个的备选c++实现mclDefaultPrintHandlermclDefaultErrorHandler,则必须声明函数外来的“C”.例如:

extern "C" int myPrintHandler(const char *s);

生成的函数MATLAB文件

中指定的每个MATLAB文件MATLAB编译器SDK命令行,该产品生成两个函数,即mlx功能和mlf函数。这些生成的函数都执行相同的操作(调用MATLAB文件函数)。这两个函数有不同的名称,呈现不同的接口。每个函数的名称基于MATLAB文件中第一个函数的名称(sierpinski,在本例中);每个函数都以不同的三字母前缀开头。

请注意

对于C共享库,MATLAB编译器SDK生成mlx而且mlf如本节所述。对于c++共享库,该产品生成mlx功能与C共享库相同。但是,该产品产生了一个修改mlf具有这些差异的功能:

  • mlf,以保持与R13的兼容性。

  • 函数的参数是mwArray而不是mxArray

mlx接口功能

以前缀开头的函数mlx采用与MATLAB mex函数相同的参数类型和数量。(更多关于mexs函数的细节,请参阅外部接口文档。)第一个论证,nlhs,是输出参数的个数,第二个参数,plhs,是一个指向数组的指针,函数将用所请求的返回值数量填充该数组。(“"是" left- side "的缩写——MATLAB表达式中的输出变量是赋值运算符左边的变量。)第三和第四个参数是输入的数量和包含输入变量的数组。

void mlxSierpinski(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])

mlf接口功能

生成的第二个函数以前缀开始mlf.该函数期望它的输入和输出参数作为单独的变量传入,而不是打包到数组中。如果函数能够产生一个或多个输出,则第一个参数是调用方请求的输出数量。

void mlfSierpinski(int nargout, mxArray** x, mxArray** y, mxArray*迭代,mxArray* draw)

在这两种情况下,生成的函数都为它们的返回值分配内存。如果您不删除此内存(通过mxDestroyArray)当你完成输出变量,你的程序将泄漏内存。

您的程序可以调用这些函数中的任何一个更方便,因为它们都以相同的方式调用MATLAB文件函数。大多数程序可能调用mlf类所需的额外数组mlx的形式。示例程序triangle.c调用mlfSierpinski

mlfSierpinski(2, &x, &y,迭代,绘制);

在这个调用中,调用者请求两个输出参数,x而且y,并提供两个输入,迭代而且

如果将输出变量传递给mlf函数不是NULL,则mlf函数将尝试释放它们使用mxDestroyArray.这意味着您可以在连续调用中重用输出变量mlf函数,而不用担心内存泄漏。这也意味着你必须通过考试或所有输出变量的有效MATLAB数组,否则您的程序将失败,因为内存管理器无法区分未初始化(无效)数组指针和有效数组。它将尝试释放非NULL的指针——释放无效指针通常会导致分段错误或类似的致命错误。

使用varargin和varargoutMATLAB函数接口

如果您的MATLAB函数接口使用变长度输入宗量varargout,则必须将它们作为单元格数组传递。例如,如果你有N变长度输入宗量S,你需要创建一个单元格数组的大小1)×(n.同样的,varargoutS作为一个单元格数组返回。的长度varargout等于函数调用中指定的返回值的数目减去实际传递的变量的数目。如在MATLAB软件中,单元格数组表示varagout必须是最后一个返回变量(在第一个输入变量之前的变量)和单元格数组表示变长度输入宗量S必须是函数调用的最后一个正式参数。

有关创建单元格数组的信息,请参阅外部接口文档中的C MEX函数接口。

例如,考虑这个MATLAB文件接口:

[a,b,varargout] = myfun(x,y,z,varargin)

对应的C接口为

void mlfMyfun(int numofretars, mxArray **a, mxArray **b, mxArray **varargout, mxArray *x, mxArray *y, mxArray *z, mxArray *varargin)

在这个例子中,元素的数量varargout(numofretars - 2),在那里2表示两个变量,一个而且b,被归还。这两个变长度输入宗量而且varargout都是单行、多列单元格数组。

谨慎

c++共享库接口不支持金宝app变长度输入宗量使用零(0)个输入参数。使用空对象调用程序mwArray的结果在打包库中接收一个空数组Nargin = 1.C共享库接口允许您调用mlfFOO(空)(打包的MATLAB代码将其解释为输入参数个数= 0).然而,调用FOO ((mwArray)零)使用c++共享库接口,使打包的MATLAB代码看到一个空数组作为第一个输入和解释输入参数个数= 1

例如,将一些MATLAB代码打包为c++共享库使用变长度输入宗量作为MATLAB函数的输入参数列表。有MATLAB代码显示变量输入参数个数.使用函数调用库喷火()它不会打包,产生以下错误消息:

……”喷火':函数不接受0参数
将库命名为:
mwArray垃圾;喷火(垃圾);
喷火((mwArray)零);
在运行时,输入参数个数= 1.在MATLAB中,喷火()输入参数个数= 0而且FOO ([])输入参数个数= 1

的c++接口MATLAB使用varargin和varargout。c++mlx接口为MATLAB函数不改变,即使函数使用变长度输入宗量varargout.但是,如果使用MATLAB函数,则c++函数接口(第二组函数)会发生变化变长度输入宗量varargout

例如,查看使用的各种MATLAB函数签名的生成代码变长度输入宗量varargout

请注意

为简单起见,下面的示例中只显示了生成的c++函数签名的相关部分。

函数varargout = foo(varargin)

函数varargout = foo(i1, i2, varargout)

函数[o1, o2, varargout] = foo(varargin)

函数[o1, o2, varargout] = foo(i1, i2, varargout)

检索MATLAB运行时使用共享库时的状态信息

类中检索特定信息时,可以调用函数MATLAB运行时状态。详细信息请参见为共享库设置和检索MATLAB运行时数据

另请参阅

相关的话题