ubuntu16.04下MATLAB和C++混编(基于ROS,不含VS类别的编译器)

如题,真的是一个很艰辛的过程,在windows下的话,在VS下的话,一切问题都不是问题。

但是,现在需要在ubuntu下的ROS中实现c++和MATLAB混编,就很鸡肋。

------------------------------------------------------------------------------------------------------------------------------------------------------------

0.在终端进入matlab操作区域
matlab -nodesktop -nosplash 

1.设置matlab的编译器
输入并执行如下命令:mex –setup
在出现的编译器中,选择mex -setup C++

再输入命令:mbuild –setup 
再选择mex -setup C++ -client MBUILD

设置结束,出现 “MBUILD 配置为使用 'g++' 以进行 C++ 语言编译。”

2.编写.m文件

function result=lib_add(a,b)
%UNTITLED4 此处显示有关此函数的摘要
%   此处显示详细说明
result = a+b;
end


3.编译.m文件
在ubuntu下编译.m文件,后面在路径配置的时候很关键。
执行下面的代码时,要解决gcc和g++的版本问题,在前面的博客中已经提到在UBUNTU16.04中要如何解决这个问题。
此外还遇到了找不到libstdc++.so.6的问题,此时全盘搜索,再将该文件复制到对应的MATLAB文件夹中即可。

代码要在MATLAB中编!//其实在终端打开MATLAB,输入命令也是可以的。

扫描二维码关注公众号,回复: 3957367 查看本文章

mcc -W cpplib:libMypr -T link:lib FrequencyDomain.m

上述代码编译完成之后,生成libMypr.h、libMypr.cpp、 libMypr.so、 libMypr.exports这四个文件,也是我们在c++中调用所需要的

4.编写C++代码,并将.cpp文件和编译的.m文件放在统一文件夹下

#include "mclmcrrt.h"  
#include "mclmcr.h"  
#include "mclcppclass.h"  
#include "matrix.h"  
#include <iostream>  
#include "libMypr.h"

using namespace std;

int main(int argc, char* argv[])    
{    
   //初始化, 在C++调用matlab时,必须要进行初始化。  
    if( !libMyprInitialize())    
    {    
        printf("Could not initialize !");    
        return -1;      
    }    

  double a[3] = {1,2,3};  
   mwArray m_a(3,1, mxDOUBLE_CLASS);
   m_a.SetData(a,3);
   double b[3] = {4,5,6};
   mwArray m_b(3,1, mxDOUBLE_CLASS);
   m_b.SetData(b,3);
   mwArray result;
   lib_add(3,result,m_b,m_b);

   // 后面是一些终止调用的程序    
    // terminate the lib       
    libMyprTerminate();           
    return 0;    
}      
 

5.编译方法一,通过指令:

编译之前,先新建一个test文件夹,把所有的文件都放进去吧,包括cpp文件中include的各种matlab中的h文件。

1)生成编译文件test.o

 g++ -c test.cpp /usr/local/MATLAB/R2017b/extern/include/ -o test.o

改进为:g++ -c test.cpp -L/home/zp/桌面/test/mat.h-L/home/zp/桌面/test/mclmcr.h -L/home/zp/桌面/test/libMypr.h -L/home/zp/桌面/test/matrix.h -L/home/zp/桌面/test/mclbase.h -L/home/zp/桌面/test/mclcppclass.h -L/home/zp/桌面/test/mclmcrrt.h -L/home/zp/桌面/test/tmwtypes.h -o test.o

g++: warning: /usr/local/MATLAB/R2017b/extern/include/: linker input file unused because linking not done

使用改进后的语句就没有上述的warning啦,主要是把include中的h文件都写出来,这样才能正确将输入全部用起来,并生成o文件。
2)设置matlab动态文件路径

export LD_LIBRARY_PATH="/home/zp/桌面/test:/usr/local/MATLAB/R2017b/runtime/glnxa64 :$LD_LIBRARY_PATH"

3)生成执行文件testApp

g++ -o testApp test.o -L/home/zp/桌面/test-/usr/local/MATLAB/R2017b/runtime/glnxa64 -lmwmclmcrrt  -L/home/zp/桌面/test-lMypr

修改后:

g++ -o testApp test.o -L/home/zp/桌面/test-/usr/local/MATLAB/R2017b/runtime/glnxa64 -L/home/zp/桌面/test/libmwmclmcrr.so   -L/home/zp/桌面/test/libMypr.so 

error:/usr/bin/ld: 找不到 -lmwmclmcrrt

/usr/bin/ld: 找不到 -lMypr

solution:

联网:(libXX是libmwmclmcrrt)

$ sudo apt-get install apt-file

$ apt-file update

$ apt-file search libXX.so

apt-file 将列出所有包含libXX.so文件的apt包,

选择相应的包用apt-get安装即可。通常请选择带dev的包安装,上述三步中,第二步的时间较长。

然鹅,执行第三步的搜索之后,并未出现所谓的安装包,搜索结果为空。

此路不通。

继续,使用修改后的代码,直接找到对应的.so文件,然后指定地址即可。找不到的问题解决了。

然鹅,编译又出现了新错误:

test.o:在函数‘main’中:
test.cpp:(.text+0x29):对‘libMyprInitialize’未定义的引用
test.cpp:(.text+0x12e):对‘add(int, mwArray&, mwArray const&, mwArray const&)’未定义的引用
test.cpp:(.text+0x133):对‘libMyprTerminate’未定义的引用
test.o:在函数‘mwException::mwException()’中:
test.cpp:(.text._ZN11mwExceptionC2Ev[_ZN11mwExceptionC5Ev]+0x42):对‘mclcppCreateError_proxy’未定义的引用
test.o:在函数‘mwException::mwException(char const*)’中:
test.cpp:(.text._ZN11mwExceptionC2EPKc[_ZN11mwExceptionC5EPKc]+0x56):对‘mclcppCreateError_proxy’未定义的引用
test.o:在函数‘mwException::mwException(error_info*, bool)’中:
test.cpp:(.text._ZN11mwExceptionC2EP10error_infob[_ZN11mwExceptionC5EP10error_infob]+0x5f):对‘ref_count_obj_addref_proxy’未定义的引用
test.cpp:(.text._ZN11mwExceptionC2EP10error_infob[_ZN11mwExceptionC5EP10error_infob]+0x76):对‘mclcppCreateError_proxy’未定义的引用
test.o:在函数‘mwException::~mwException()’中:
test.cpp:(.text._ZN11mwExceptionD2Ev[_ZN11mwExceptionD5Ev]+0x34):对‘ref_count_obj_release_proxy’未定义的引用
test.o:在函数‘mwException::what() const’中:
test.cpp:(.text._ZNK11mwException4whatEv[_ZNK11mwException4whatEv]+0x25):对‘error_info_get_message_proxy’未定义的引用
test.o:在函数‘mwException::raise_error()’中:
test.cpp:(.text._ZN11mwException11raise_errorEv[_ZN11mwException11raise_errorEv]+0x2a):对‘mclcppGetLastError_proxy’未定义的引用
test.o:在函数‘mwArray::mwArray()’中:
test.cpp:(.text._ZN7mwArrayC2Ev[_ZN7mwArrayC5Ev]+0x35):对‘mclGetEmptyArray_proxy’未定义的引用
test.o:在函数‘mwArray::mwArray(unsigned long, unsigned long, mxClassID, mxComplexity)’中:
test.cpp:(.text._ZN7mwArrayC2Emm9mxClassID12mxComplexity[_ZN7mwArrayC5Emm9mxClassID12mxComplexity]+0x50):对‘mclGetMatrix_proxy’未定义的引用
test.o:在函数‘mwArray::~mwArray()’中:
test.cpp:(.text._ZN7mwArrayD2Ev[_ZN7mwArrayD5Ev]+0x24):对‘ref_count_obj_release_proxy’未定义的引用
test.o:在函数‘mwArray::SetData(double*, unsigned long)’中:
test.cpp:(.text._ZN7mwArray7SetDataEPdm[_ZN7mwArray7SetDataEPdm]+0x2b):对‘array_ref_set_numeric_mxDouble_proxy’未定义的引用
collect2: error: ld returned 1 exit status
 

gcc和g++的指令说明:https://blog.csdn.net/arackethis/article/details/43342655

-o:指定生成可执行文件的名称。使用方法为:g++ -o afile file.cpp file.h ... (可执行文件不可与待编译或链接文件同名,否则会生成相应可执行文件且覆盖原编译或链接文件),如果不使用-o选项,则会生成默认可执行文件a.out。

-c:只编译不链接,只生成目标文件。
 

6.编译方法二,通过CMakelists:

make的时候,出现了以下解决了很久很久的问题,唉:

[100%] Linking CXX executable ../VIO
../../../../lib/libORB_SLAM2.so:对‘mclGetMatrix_proxy’未定义的引用
../../../../lib/libORB_SLAM2.so:对‘error_info_get_message_proxy’未定义的引用
../../../../lib/libORB_SLAM2.so:对‘mclcppGetLastError_proxy’未定义的引用
../../../../lib/libORB_SLAM2.so:对‘array_ref_set_numeric_mxDouble_proxy’未定义的引用
../../../../lib/libORB_SLAM2.so:对‘mclGetEmptyArray_proxy’未定义的引用
../../../../lib/libORB_SLAM2.so:对‘mclcppCreateError_proxy’未定义的引用
../../../../lib/libORB_SLAM2.so:对‘ref_count_obj_release_proxy’未定义的引用
../../../../lib/libORB_SLAM2.so:对‘array_ref_get_numeric_mxDouble_proxy’未定义的引用
../../../../lib/libORB_SLAM2.so:对‘FrequencyDomain(int, mwArray&, mwArray const&, mwArray const&, mwArray const&, mwArray const&, mwArray const&, mwArray const&)’未定义的引用
collect2: error: ld returned 1 exit status
CMakeFiles/VIO.dir/build.make:300: recipe for target '../VIO' failed
make[2]: *** [../VIO] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/VIO.dir/all' failed
make[1]: *** [CMakeFiles/VIO.dir/all] Error 2
Makefile:127: recipe for target 'all' failed
make: *** [all] Error 2

找了快一天半的原因,发现是没添加好mylib.so,需要将其在cmakelists中进行连接,并且再生成共享库的内部要加入MATLAB生成的h文件和cc文件以及so文件。

百度查找相关问题的时候,大多是mclmcrrt.lib未加入,但是我并没有找到,问题也解决了。

猜你喜欢

转载自blog.csdn.net/Pancheng1/article/details/83097684