1. 程式人生 > >ubuntu16.04下MATLAB和C++混編(基於ROS,不含VS類別的編譯器)

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,輸入命令也是可以的。

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未加入,但是我並沒有找到,問題也解決了。