本文讲解如何在mac+xcode上用C/C++调用matlab,并给出一个极简单的应用,kmeans.
我们的目标是:跑通/Applications/MATLAB_R2013a.app/extern/examples/eng_mat/engdemo.cpp
1)修改mac环境变量$PATH & $DYLD_LIBRARY_PATH
终端下:
export PATH='/Applications/MATLAB_R2013a.app/bin':$PATHecho $PATHexport DYLD_LIBRARY_PATH='/Applications/MATLAB_R2013a.app/bin/maci64:/Applications/MATLAB_R2013a.app/sys/os/maci64':$DYLD_LIBRARY_PATHecho $DYLD_LIBRARY_PATH
~/.bash_profile ~/.bash_login ~/.profile
其实bash再启动是只读上面文件的一个,而读取的顺序则是依照上面的顺序。也就是说读到bash_profile就不读后面的了,如果bash_profile不存在,后面的才能有机会。
ok,修改过profile之后,注销,重新login就会修改$PATH 和 $DYLD_LIBRARY_PATH了。
2) 跑demo
cd /Applications/MATLAB_R2013a.app/extern/examples/eng_matg++ -o engdemo_terminal engdemo.cpp -I/Applications/MATLAB_R2013a.app/extern/include/ -L/Applications/MATLAB_R2013a.app/bin/maci64 -leng -lmx -lm -lmat -lut -lstdc++
可以看到link的几个动态链接库(mac下为.dylib,相当于windows下的dll),eng (libeng.dylib),mx(libmx.dylib),m(libm.dylib),mat(libmat.dylib),ut(libut.dylib),stdc++(标准链接库)分别在/usr/lib/ 和/Applications/MATLAB_R2013a.app/bin/maci64下。
编译完成,运行:
./engdemo_terminal
运行shell code和在一起就是这样:
cd /Applications/MATLAB_R2013a.app/extern/examples/eng_matexport PATH='/Applications/MATLAB_R2013a.app/bin':$PATHecho $PATHexport DYLD_LIBRARY_PATH='/Applications/MATLAB_R2013a.app/bin/maci64:/Applications/MATLAB_R2013a.app/sys/os/maci64':$DYLD_LIBRARY_PATHecho $DYLD_LIBRARY_PATHg++ -o engdemo_terminal engdemo.cpp -I/Applications/MATLAB_R2013a.app/extern/include/ -L/Applications/MATLAB_R2013a.app/bin/maci64 -leng -lmx -lm -lmat -lut -lstdc++./engdemo_terminal
1)配置项目属性如下:(项目名没改,本来是测试mysql的,不要怀疑我是脑残贴错图……囧)
include:
library:
link:(符号链接)
动态链接库:
这里注意要将/Applications/MATLAB_R2013a.app/bin/maci64下的.dyilb文件都copy到目标文件夹下,不然会报错诸如
dyld: Library not loaded: @rpath/libeng.dylib Referenced from: /Users/mba/Library/Developer/Xcode/DerivedData/mysqlTest-enzwyvjtfdmbfnebxteublhyjhrd/Build/Products/Release/mysqlTest Reason: image not found
或者
dyld: Library not loaded: @rpath/libut.dylib Referenced from: /Users/mba/Library/Developer/Xcode/DerivedData/mysqlTest-enzwyvjtfdmbfnebxteublhyjhrd/Build/Products/Release/mysqlTest Reason: image not found
另外注意,/Applications/MATLAB_R2013a.app/extern/lib/maci64下的fexport.map, mexFunction.map和mexLibrary.map三个map文件是用不到的。
2)更改Debug模式为Release
因为matlab给出的接口是release的,所以我们的项目也要相应改成release的。
代码涉及matlab engine的创建,mex类型的创建,C基本数据类型(double)与matlab mx类型的相互转换,以及如何利用kmeans进行聚类。
//// main.cpp// mysqlTest//// Created by Rachel on 13-12-6.// Copyright (c) 2013年 ZJU. All rights reserved.//#include #include #include #include "engine.h"#define BUFSIZE 256int main(){ printf("test\n"); Engine *ep;//matlab engine mxArray *T = NULL, *result = NULL; char buffer[BUFSIZE+1]; double time[10] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 }; /* * Call engOpen with a NULL string. This starts a MATLAB process * on the current host using the command "matlab". */ if (!(ep = engOpen(""))) { fprintf(stderr, "\nCan't start MATLAB engine\n"); return EXIT_FAILURE; } T = mxCreateDoubleMatrix(1, 10,mxREAL); //transform double to mxArray(double of C++转mxArray) memcpy((void *)mxGetPr(T), (void *)time, sizeof(time)); engPutVariable(ep, "T", T);//传入matlab //transform mxArray to double(mxArray转double) memcpy((void*)time, (void*)mxGetPr(T), sizeof(mxGetPr(T))*10);//注意要乘以time的长度 buffer[BUFSIZE] = '\0'; engOutputBuffer(ep, buffer, BUFSIZE); engEvalString(ep, "D = kmeans(T,3)"); mxDestroyArray(T); mxDestroyArray(result); return EXIT_SUCCESS;}
参考:
1. http://www.cnblogs.com/xitang/archive/2011/09/15/2177924.html
2. stackoverflow
欢迎关注本博客和新浪微博Rachel____Zhang
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow