PS:此文章僅作為個人記錄使用,代碼屬於私密,故無法公開;
以C++類classifier為例,文件保存於百度網盤 https://pan.baidu.com/s/1c2AwhaS(需密碼)
系統:Ubuntu 15.04
參考資料:
編程中出現的錯誤:
java編譯時出現undefined symbol:... 此種情況大部分原因是需要在原來的C++庫中添加鏈接某lib....so文件(undefined symbol:
_ZN5boost6system15system_categoryEv)
java編譯時出現Error: Could not find or load main class test:此種情況是因為javac -cp /home/fiona/20160419/SG_FORTESTSUCC/swig/java/myclassifier.jar test.java 未添加本地目錄,應該為javac -cp .:/home/fiona/20160419/SG_FORTESTSUCC/swig/java/myclassifier.jar test.java (Error: Could not find or load main class [duplicate])
正文:
0. C++動態庫編譯
將classifier.cpp編譯成C++動態庫libclassifier.so, 並將動態庫libclassifier.so放入系統的庫文件中
圖1 編譯C++動態庫
1. 利用SWIG將C++接口轉換為Java接口
1.1 SWIG接口文件(.i)的編寫和使用
@ SWIG需要編寫一個后綴為.i的接口文件,用來指定需要從C++類中導出的接口函數;
圖2 swig的接口文件
模塊名由指定的%module來給出(或者用-module命令行選項)。這段指示性文字必須寫在文件的頭部,並且在使用時將這個模塊名作為擴展模塊對象來使用(此外,這個模塊名經常在目標語言中被定義成一個命名空間來使用)。如果模塊名在命令行已經被給出了,系統將不考慮由%module標示的模塊名了。
所有在%{...%}塊內的東西將被簡單作為結果逐字拷貝到SWIG創建的wrapper(包裝)文件中。這部分大部分被用來包括頭文件和生成wrapper代碼需要的其它聲明。
STL/C++庫的轉化
這一部分的庫模塊提供訪問部分標准C++庫包括STL的方法。使SWIG支持STL還是一個正在努力中的事情。
SWIG對於一些語言模塊的支持使較全面的但是對很少用到的庫則支持的很少。
下面就是表示了C++類和支持的C++庫 以及SWIG接口文件的對應表
C++ class C++ Library file SWIG Interface library file
std::deque deque std_deque.i
std::list list std_list.i
std::map map std_map.i
std::pair utility std_pair.i
std::set set std_set.i
std::string string std_string.i
std::vector vector std_vector.i
這個表應該說還沒有很完善。一些語言模塊支持上面的一個子集而另一些支持擴展的STL類.請仔細尋找相關語言庫目錄下的庫文件。
@ 基於編寫好的.i文件,使用swig命令生成java類和C++接口的wrap文件
圖3 swig命令
執行$swig -c++ -java -package com.classifier -outdir ./ -I../ myclassifier.i
swig參數說明:
1)-c++ -java
告訴swig將C++接口轉換為java接口。如果是將C接口轉換為java接口,就不需要-c++,直接寫 swig -java就可以;
2)-package
生成的java類的包的名稱;
3)-I
myclassifier.i 中include的.h文件的路徑。
執行swig命令后,將在swig路徑下生成一下幾個文件:
1)myclassifier_wrap.cxx
C++文件,包裝器文件。它將C++類的方法轉換為C的函數;
2)myclassifier.java
與swig中定義的module同名的java類;
3)myclassifierJNI.java
C++類中的方法在此文件中轉化為Java的靜態方法;
4)Classifier.java
與C++類同名的Java類,其中包含需要導出的成員函數;
5)SWIG_....java
swig將自定義的C++類型轉換生成的Java類
1.2 編譯myclassifier_wrap.cxx文件為.so庫文件
必須的文件:jni.h, jni_md.h,剛才編譯好的C++庫文件libclassifier.so
圖4 jni所使用的C++庫的生成
需將生成的.so文件放入系統庫文件夾中,jni將通過libmyclassifier.so庫調用libclassifier.so庫中的類和方法。
到現在為止,就通過SWIG將C++接口轉換為Java接口。
2. 使用SWIG生成的Java接口
2.1 編譯Java文件
進入swig目錄,SWIG生成的Java文件現在都在這里。
$javac *.java 生成class文件 =》
剛才我們設定的java包是com.classifier,於是創建com/classifier目錄,將class文件移動到該目錄下並打包
$jar -cvf myclassifier.jar ./com生成myclassifier.jar包
圖4 編譯java文件
2.2 測試
需導入myclassifier.jar包,同時所使用的庫文件需放在系統的庫文件夾下或者指定的位置
圖5 java測試程序
圖6 java編譯指令
至此,成功使用SWIG將C++接口轉為Java接口。