收藏 分销(赏)

在MATLAB环境下访问外部函数的共享库文件.doc

上传人:二*** 文档编号:4522496 上传时间:2024-09-26 格式:DOC 页数:11 大小:101KB 下载积分:5 金币
下载 相关 举报
在MATLAB环境下访问外部函数的共享库文件.doc_第1页
第1页 / 共11页
本文档共11页,全文阅读请下载到手机保存,查看更方便
资源描述
在MATLAB环境下访问外部函数的共享库文件,必须首先把该库文件加载到内存中。一旦加载成功,就能直接在MATLAB中直接请求关于函数的任何信息。而当不再需要该库时,就应当及时把库文件从内存中卸载以节省内存开销。 加载库 语法:loadlibrary(‘shrlib’,’hfile’) 其中shrlib为加载的动态链接库文件名(filename.dll),hfile为头文件名,它包含函数原型。例如,当加载包含MATLAB中mx程序的libmx库时,可以使用下列语句。 hfile=[matlabroot’\extern\include\matrix.h’]; loadlibray(‘libmx’, hfile) 卸载库 语法:unloadlibrary libmx 使用两个函数可以获取加载库的信息: libfunctions(‘libname’) or libfunctions libname libfunctionsview(‘libname’) or libfunctionsview libname 这两个函数的不同之处在于显示结果的方式不同,后者是以图形的方式显示在新的窗口中。而前者返回库libmx中有哪些可用的函数。请看示例: libfunctions libmx Methods for class lib.libmx: mxAddField mxGetFieldNumber mxIsLogicalScalarTrue mxArrayToString mxGetImagData mxIsNaN mxCalcSingleSubscript mxGetInf mxIsNumeric mxCalloc mxGetIr mxIsObject mxClearScalarDoubleFlag mxGetJc mxIsOpaque mxCreateCellArray mxGetLogicals mxIsScalarDoubleFlagSet 如果加上命令开头-full,则可以显示函数返回值的细节。 libfunctions libmx -full Methods for class lib.libmx: [mxClassID, MATLAB array] mxGetClassID(MATLAB array) [lib.pointer, MATLAB array] mxGetData(MATLAB array) [MATLAB array, voidPtr] mxSetData(MATLAB array, voidPtr) [lib.pointer, MATLAB array] mxGetPr(MATLAB array) [MATLAB array, doublePtr] mxSetPr(MATLAB array, doublePtr) uint8 mxIsFinite(double) uint8 mxIsInf(double) 值得注意的是,这两个函数返回值的类型均是MATLAB的数据类型,虽然函数是利用C语言编写的。 调用库函数 一旦库函数被加载到了内存空间,只要指定库名、函数名和变量就可以使用calllib函数调用库中的任何函数了。语法格式: calllib(‘libname’,’funcname’,arg1,…,argn) 下列语句显示如何操作: hfile=['C:\MATLAB7\extern\include\matrix.h']; loadlibrary(‘libmx’,hfile); y=rand(4,7,2); %produce a 3D array, there are 56 elements in it calllib(‘libmx’,’mxGetNumberOfElements’,y) ans= 56 Calllib(‘libmx’,’mxGetClassID’,y) ans= mxDouble_CLASS 传递变量 当调用外部库里的函数时,该为函数提供哪种类型的变量呢?MATLAB的extern\examples\shrlib\shrlibsample库里对每一种特殊的变量类型都作出了说明。但我们首先必须把该库文件的路径添加到MATLAB的搜索路径中来,或者使该库文件所在的目录成为当前目录,两种做法的命令如下。 addpath(‘C:\MATLAB7\extern\examples\shrlib’) cd(‘C:\MATLAB7\extern\examples\shrlib’) 下面的例子就是加载该库并显示了其中的一些函数。 loadlibrary shrlibsample shrlibsample.h libfunctions shrlibsample –full 执行上述两行后,返回: Functions in library shrlibsample: [double, doublePtr] addDoubleRef(double, doublePtr, double) double addMixedTypes(int16, int32, double) [double, c_structPtr] addStructByRef(c_structPtr) double addStructFields(c_struct) c_structPtrPtr allocateStruct(c_structPtrPtr) voidPtr deallocateStruct(voidPtr) doublePtr multDoubleArray(doublePtr, int32) [lib.pointer, doublePtr] multDoubleRef(doublePtr) int16Ptr multiplyShort(int16Ptr, int32) string readEnum(Enum1) [string, string] stringToUpper(string) 这里所有的函数都是用C语言编写的。 一些通用的规则 在函数的输入输出变量问题上,以下几点应注意: 1.许多变量类型,象int32、double与C语言的数据类型非常相象。这些变量只需要传递MATLAB型的数据就可以了。 2.而有些C语言的变量类型,象**double、还有预定义型与标准MATLAB数据类型是完全不同的。这种情况下,有两种选择,要么给外部函数的入参传递标准的MATLAB数据类型,让MATLAB程序自动转化,要么先使用MATLAB提供的转化函数,如libstruct、libpointer自己转化。关于转化,可以参考Data Conversion。 3.C语言通常可以按形参传递变量,但MATLAB不支持这种做法,不过可以创造MATLABPtr或PtrPtr型的变量,去兼容C语言的形参。 4.C语言通常还可以通过形参来返回输入变量的值,而MATLAB需要额外的变量来获得返回值。 传递变量的通用规则 1.库函数传递形参时,标量不必非得声明。 2.如果库函数使用单下标来引用二维矩阵元素时,请记住,C语言是逐行处理矩阵元素,而MATLAB是按列优先处理的。因此迎合C语言的习惯,可以在给MATLAB函数传递变量之前把矩阵进行转置,从函数返回后再转置回来就行了。 3.由上可知,当传递的矩阵超过二维时,MATLAB会改变矩阵的行列结构,为了确保矩阵的结构不被破坏,可以事先记录矩阵的结构,在调用结束后利用reshape函数还原即可。例如: vs=size(vin); %suppose the dimention of vector vin is 2-by-5-by2 vout=calllib(‘shrlibsample’,’multDoubleArray’,vin,20); %dimention have been altered ans= 2 10 vout=reshape(vout,vs); %Restore the array to 2-by-5-by-2 size(vout) ans= 2 5 2 4.当支持可选参数时,可用一空矩阵来传递一个NULL型参数。这是在变量为Ptr或PtrPtr型时唯一的选择。 传参 外部库的许多函数是传递形参的,为了能与这些函数交互,MATLAB通常传递一个叫“指针对象”的变量,不过别把它与传参混同了。 数据转化 在多数情况下,传递给外部库函数或从外部库函数返回的数据类型自动被MATLAB转化,然而,或许你偶尔也希望有些时侯能手动转化: 1.当需要传递相同的数据给一系列库函数时,可能手动转化要比让MATLAB自动转化更为明智,更能节省时间。 2.当传递大结构的数据时,手动转化数据使之匹配C结构而不是直接采用通用的MATLAB型数据的做法,比直接使用libstruct函数把C结构型的数据转换成MATLAB型数据更能节省内存。 3.当外部函数使用超过一层引用(例如,指向指针的指针变量double **)时,用libpointer函数构造一个参数,比直接让MATLAB自动转化数据要好。 原始类型 共享库接口支持所有标准C数据类型。下表显示了C与MATLAB等价的数据类型。 C类型(32位机器) 等价MATLAB类型 char, byte int8 unsigned char, byte uint8 short int16 unsigned short uint16 int, long int32 unsigned int, unsigned long uint32 float single double double char * string(1-by-n char array) 下表显示的lib.pointer类中的数据类型,非MATLAB标准类型 C数据类型(32位机器) 扩展MATLAB数据类型 integer pointer types (int *) (u) int (size) Ptr float * singlePtr double * doublePtr mxArray * MATLAB array void * voidPtr type ** same as typePtr with an added Ptr(e.g.,double ** is doublePtrPtr) MATLAB可以自动把转化数据为外部库函数所需要的任何原型数据,这就意味着可以传递一个双精度型数据给一个8位整数型变量。下述C函数接受短整型、整型和双精度型数据: double addMixedTypes(short x, int y, double z) { return (x+y+z); } 你可以极其简单地在MATLAB中只传递给该函数以双精度变量,MATLAB自动判断每个变量接受何种类型的变量,并作近似转化。 calllib (‘shrlibsample’,’addMixedTypes’, 127, 33000, pi) ans= 3.3130e+004 转化参数 当外部函数原型定义一个形参时,MATLAB能自动地把一个按值传递的变量转化为形参。因此,当给一个双精度指针变量赋一双精度变量时,MATLAB会自动地把该双精度变量转化为双精度形参。 addDoubleRef是一个接受双精度指针型形参的函数: double addDoubleRef( double x, bouble *y, double z) { return (x+ *y +z); } 用三个双精度变量调用该函数,MATLAB自动处理数据转化: calllib (‘shrlibsample’, ‘addDoubleRef’, 1.78, 5.42, 13.3) ans= 20.5000 字符串 当变量需要字符型指针数据时,你可以传递一个MATLAB型字符串(矩阵)。下述C函数接受一个字符指针型数据: char * stringToUpper (char *input) { char *p=input; if (p!=NULL) while (*p!=0) *p++=toupper(*p); return input; } libfunctions显示,你可以用一个MATLAB字符串作为输入。 libfunctions shrlibsample –full [string, string] stringToUpper (string ) 定义一个MATLAB字符矩阵str,把它传递给变量。 str=’This was a Mixed Case string’; %MATLAB中字符串以“’”号对表示 calllib(‘ shrlibsample’, ‘stringToUpper’, str) ans= THIS WAS A MIXED STRING 注意:虽然MATLAB传递给变量的很象字符型的形参,但它并不真正的参数类型。因为它并不包括MATLAB字符矩阵str的地址。因此当函数执行完毕时,字符串的值并未改变。 枚举型 如果变量被定义为C中的枚举型,你可以传递枚举型或一个与枚举值等价的整数。 shrlibsample库中的readEnum函数返回与传入变量相应的枚举型。下述为Enum1的定义和C语言函数readEnum: enum Enum1 {en1=1,en2, en4=4} TEnum1; char *readEnum(TEnum1 val) { switch (val) { case 1:return “you chose en1”; case 2:return “you chose en2”; case 4:return “you chose en4”; default: return “enum not defined”; } } MATLAB,你可以用一个枚举型字符或等价的整数来表示枚举型数据。上述中定义的枚举型数据TEnum1中,en4与4等价: calllib (‘shrlibsample’, ‘readEnum’, ‘en4’) ans= you chose en4 calllib (‘shrlibsampel’, ‘readEnum’, 4) ans= you chose en4 结构体型 当库函数接受结构体型变量时,你需要给它传递与在结构体定义时拥有相同域名的结构体变量。为了确定结构体变量的域和类型,你可以: 1.查询库文档 2.在加载到MATLAB的库的头文件中寻找结构体的定义。 你也可以在MATLAB中采用下述步骤来确定外部函数定义过的结构体的域名。 1.利用libfunctionsview函数来显示正在使用的库函数的信息,它包含了每一个函数所做用的结构体数据的名字。当键入libfunctionsview shrlibsample命令时,MATLAB就会在新窗口中显示库函数的信息。 如:double addStructFields (c_struct) 2.利用libstruct函数获取结构体定义模型。 如s=libstruct( ‘c_struct’); 3.继而利用get函数返回结构体数据的域名。 如get(s) p1:0 p2:0 p3:0 4.利用calllib函数初始化所需要传递给库函数的域值。 如s.p1=478; s.p2=-299; s.p3=1000; calllib (‘shrlibsample’, ‘addStructFields’, s) 当你利用calllib函数创建或初始化结构体数据时,不必去匹配结构体的数据域,MATLAB会自动转化数据类型。 指定结构体域名 下面是在为外部库函数传递结构体数据时一般的做法: 1.结构体数据可能只包含了定义中很少的一部分域,MATLAB会把其余的域初始化为0. 2.你所使用的任何结构体的域名须与定义中的域名一致。 3.结构体中不能包含库函数中未定义过的域名。 传递MATLAB结构体 与其他的数据类型一样,当外部函数接受结构体变量数据类型时,就可以传递一个MATLAB型结构体数据给它。结构体的域名必须与库函数定义中的域名一致,而数值类型则可以不同,由MATLAB自动转换完成。 如shrlibsample共享库中定义了这样的C结构和函数: struct c_struct { double p1; short p2; long p3; }; double addStructField (struct c_struct st ) { double t=st.p1 +st.p2 +st.p3; return t; } 下面的代码完成向addStructField函数传递一个结构体变量sm,包含三个双精度数据,即传递的数值类型与C定义中的不一样,但域外必须相同,否则传递不进去: sm.p1=476; sm.p2=-299; sm.p3=1000; calllib(‘shrlibsample’, ‘addStructFields’, sm ) ans= 1177 传递结构体对象 当为外部函数传递结构体变量时,MATLAB为了确保传递成功,要求域名必须与库函数定义中的一致,而对数值类型则不加强求,由MATLAB自动转换成库函数中对应域的数值类型,并且把空域的值均初始化为零。当结构体数据较小时,这种做法很有效。然而,当重复传递一个或多个大的结构体数据时,手动转化是更明智的选择,不仅可以节省时间,还可以节省内存和空间。 使用libstruct函数 s=libstruct (‘structtype’, mlstruct) 返回值s叫做libstruct对象。虽然它实际上是MATLAB的一个对象,但它更象是一个结构体数据。这个新的所谓“结构体”的域名得自于外部库函数中结构体的域名。 例如,把MATLAB结构体sm转换成libstruct对象sc: sm.p1=476; sm.p2=-299; sm.p3=1000; sc=libstruct (‘c_struct’, sm); sm的原始结构中域值为三个双精度型,而libstruct函数转换后的sc对象的域名则与c_struct结构体一致,分别为double、short和long型。 创建空libstruct对象 s=libstruct (‘structtype’)这种调用格式可以生成域名完整,域值为0的空libstruct对象。 使用结构体作为对象 libstruct转换后的结构体实际上是lib.c_struct类中的一个对象实例,这一点可以通过whos命令的输出来验证: whos sc Name Size Bytes Class sc 1-by-1 lib.c_struct Grand total is 1 element using 0 bytes 域已经被当成了lib.c_struct类的属性来处理了。你可以利用基于对象的函数set和get来读写: sc=libstruct (‘ c_struct’ ); set (sc, ‘p1’,100, ‘p2’, 150, ‘p3’, 200 ); %对象读写须用get、set get(sc) p1:100 p2:150 p3:200 但是你也可以象处理结构体数据那样简单地对sc进行读写: sc.p1=23; %而结构体的域可以直接赋值 sc.p1 ans= 23 创建形参 你可以为外部函数按值传递大多数的变量,即使函数原型要求形参传递,然而有时你会发现这与直接给C传递形参一样揍效。 使用库指针函数 用函数libpointer构造一个形参的语法如下: p=libpointer(‘type’, ‘value’) 例如要创建一个指向int16数据类型的指针pv,就得先指定指针的类型,并以Ptr作后缀: v=int16(485); pv=libpointer(‘int16Prt’, v); 返回值pv实际就是MATLAB中lib.pointer类的一个实例。lib.pointer有属性值和数据类型。你可以用get或set函数来读或写这些属性。 get(pv) value:485 DataType:’int16Ptr’ lib.pointer类还有另外两种方法setdatatype和reshape。 methods(pv) methods for class lib.pointer:setdatatype reshape 为原始类型创建形参 如何去创建和传递指针给双精度型,又如何输出数据这里有一个简单的例子可以说明。函数multDoubleRef接受一个双精度形参同时返回双精度型。 double *multDoubleRef(double *x) { *x *=5; return x; } 输入数据x来创建一个形参xp: x=15; xp=libpointer(‘doublePtr’,x); get(xp) value:15 Datatype:’doublePtr’ 现在可以调用函数来检验结果: calllib(‘shrlibsample’, ‘multDoubleRef’, xp); get(xp, ‘value’) ans= 75 注意:xp虽然是作为x的形参而创建的,但它并非真的象C语言的指针,因为xp中并不包含x的地址,因此,当函数执行时,函数修改xp的属性值,但它并不修改x的值。 获得函数的返回值 在上述最后一例子中,从MATLAB调用的函数返回值可以通过检查修改了的输入形参来获得,但这个函数也可以通过输出变量来获得。 这个函数的MATLAB原型表明(利用libfunctions shrlibsample –full查看原型),它返回了两个输出变量,一为lib.pointer类的对象,另一为dlublePtr输入变量的属性值: libfunctions shrlibsample –full [lib.pointer, doublePtr] multDoubleRef (doublePtr) 再次运行这个例程,但这次检查返回值 x=15; xp=libpointer(‘ doublePtr’, x); [xobj, xval]=calllib(‘shrlibsample’, ‘multDoubleRef’, xp) xobj= lib.pointer xval= 75 创建结构体形参 与创建原始类型的形参相比,创建结构体的形参并非难事。下述函数只接受C语言形式的结构体形参,它的返回值是所有结构体域值之和,同时也修改了输入参量。 double addStructByRef( struct c_struct *st ) { double t=st->p1+st->p2+st->p3; st->p1=5.5; st->p2=1234; st->p3=12345678; return t; } (1)传递结构体本身 虽然这个函数期望获得一个结构体的输入参量。下列给形参传递了一个MATLAB的结构体sm,返回值是正确的,因为sm不是按址传递,所以sm的域值并未被函数修改。 sm.p1=476; sm.p2=-299; sm.p3=1000; x=calllib(‘shrlibsample’, ‘addStructByRef’, sm) x= 1177 (2)传递结构体形参 sp=libpointer( ‘c_struct’, sm); calllib(‘shrlibsample’, ‘addStructByRef’, sp ) ans= 1177 get(sp,’value’) ans= p1:5.5000 p2:1234 p3:12345678 形参指针 当变量超过一层引用(例如,uint16 **)就是这里提到的形参指针。在MATLAB中,这类变量类型都加以后缀PtrPtr。 当调用一个接受形参指针的函数时,你可以使用一个形参变量代替,MATLAB将会把该形参变量转换为形参指针。例如,外部函数allocateStruct接受一个c_structPtrPtr变量: libfunctions shrlibsample –full c_structPtrPtr allocateStruct(c_structPrtPtr) C语言编写的该函数: void allocateStruct (struct c_struct **val) { *val=(struct c_struct *) malloc(sizeof(sturct c_struct)); (*val)->p1=12.4; (*val)->p2=222; (*val)->p3=333333; } 该函数原型需要一个c_structPtrPtr型数据,但你可以只传递一个c_structPtr型数据,让MATLAB完成第二层引用。下例创建了一个空的结构体形参传递给allocateStruct函数: sp=libpointer (‘c_structPtr’); calllib( ‘shrlibsample’, ‘allocateStruct’, sp) get(sp) ans= value:[1-by-1 struct] DataType:’c_structPtr’ get(sp, ‘value’) ans= p1:12.4000 p2:222 p3:333333 完成之后,记得从内存中删除该对象以释放空间: calllib( ‘shrlibsample’, ‘deallocateStruct’, sp) MATLAB外部接口 你可以在MATLAB中调用自己编写的C函数,MATLAB会让你感觉就象调用MATLAB自身内建函数一样轻松。 MATLAB中可以调用的C函数就是MEX文件,MEX文件是MATLAB解释器能自动加载和执行的子程序。 MEX文件有几个应用: 1.不必为调用大型C程序而把它改写成MATLAB默认的M文件。 2.解决计算的一些瓶颈问题,在MATLAB中做一些循环计算时效率不如C语言。 MEX文件不适合所有的应用,MATLAB是一个高效率的系统,与C和Fortan编译相比,它能有效降低耗时。一般多数编程MATLAB均能解决,因此除非你的应用程序确实需要MEX文件,否则不必使用MEX文件。 使用MEX文件 MEX文件是C或Fortran代码的子程序,它的运行就象M文件和内建函数。MATLAB识别MEX文件是根据不同操作平台文件的扩展名,而M文件的扩展名(.m)与操作平台无关。不如操作系统下MEX文件的扩展名如下: 操作系统平台 MEX文件扩展名 HP-UX mexhpux Linux mexglx Macintosh mexmac Solaris mexsol Windows dll 你可以准确地调用MEX文件就如同调用M文件。例如,磁盘的datafun toolbox目录上有一conv2.mex的MEX文件,它能实现一个二维矩阵的转换,而conv2.m文件只包含帮助文档。如果从MATLAB内部调用函数conv2,解释器将在MATLAB的搜索路径(默认的路径有多条)上查找,直至找到第一次出现的conv2的文件和相应的扩展名,然后加载并执行。如果在同一目录上有相同文件名的MEX文件(.dll---以windows平台为例)和M文件(.m),则MEX文件优先,而帮助文档仍然从.m文件中读取。 前缀mx与mex的差别 API的程序以mx为前缀,允许你创建、访问、操作和销毁mxArrays,前缀mex的程序在MATLAB的后台工作。例如mexEvalString子程序就工作在MATLAB的工作空间对字符串运算。 为了操作MATLAB的矩阵,矩阵访问和创建库提供一套子程序,这些子程序以mx前缀开头,它们的完整文档于在线参考网页上能找到。例如,mxGetPi函数从矩阵内取回虚数的指针。 虽然访问、创建矩阵的子程序允许操纵MATLAB矩阵,但有两种情况例外,IEEE程序和内存管理程序。例如,mxGetNaN返回一双精度数据,而非mxArray型。 MATLAB数据 在你开始编制MEX文件之前,必须先了解MATLAB支持的数据类型。 1.矩阵 MATLAB只用唯一的对象类型数据--MATLAB矩阵。所有的MATLAB变量,包括标量、矢量、矩阵、字符串、元胞矩阵、结构体及对象,它们都是存储在MATLAB矩阵里。对应C语言中,MATLAB矩阵应声明为mxArray型,mxArray型数据中包括了矩阵的类型、维数、相关数据等。如果是数值变量,它还包括该变量是实数还是复数的信息,如果是稀疏矩阵,它还记录下标和非零的元素个数,如果是结构体或对象,它还包括域的个数和域名。 2.数据存储 MATLAB中的数据是按列存储,与Fortran相同,之所以采用这种习惯,是缘于MATLAB最初是用Fortran语言编写的。 例如矩阵a=[‘house’; ‘floor’; ‘porch’] a= house floor porch size(a) ans= 3 5 数据存储为 h f p o l o u o r s o c e r h 3.复数 复数在MATLAB中是最普遍的双精度类型,一个m-by-n的矩阵它的实部和虚部分别存放在m-by-n大小的矩阵中,其中m表示矩阵的行数,n表示矩阵的列数。这两个矩阵独立时由两个指向实数和虚数的指针pr、pi指着,如果是实数(如单精度的浮点数,无符号和有符号的8、16、32位整数),则虚部的指针为NULL。 4.逻辑矩阵 5.MATLAB字符串 MATLAB字符串是字符类型,它的存储方式与16位整数一样,只是没有虚部分量。与C不同的是,MATLAB字符串不以NULL结束。 6.元胞矩阵 7.稀疏矩阵 稀疏矩阵的存储习惯与满置矩阵不同,除了指向实部和虚部的指针pr、pi外,还有三个参数nzmax、ir和jc: nzmax 为一整数,它包括ir、pr的长度,如果有虚部的话,也包括pi的长度,它表示稀疏矩阵中不为零的元素的最大的个数。 ir 是一长度为nzmax的整数矩阵,它包含了pr和pi指针中相应元素的行下标。 jc是一长度为N+1的整数矩阵,它包含了元素列的信息。j的变化范围是0=<j<=N-1,jc[j]为第j列第一个非零项的
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 教育专区 > 初中其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服