Linux下SWIG封装c++接口供java使用
最近研究如何封装c++给java使用,通过调研发现swig工具能很好的实现次功能。因此把本次研究的整个流程记录下来,以供大家借鉴使用。
文件结构
本次实验的整个文件结构如下所示
xx@ubuntu:~/xx/swigtest$ tree .
.
├── com
│ └── test
│ ├── DoubleVector.class
│ ├── IntVector.class
│ ├── StrVector.class
│ ├── test.class
│ └── testJNI.class
├── demo.class
├── demo.java
├── libtest.so
├── temp
│ ├── DoubleVector.java
│ ├── IntVector.java
│ ├── StrVector.java
│ ├── test.java
│ └── testJNI.java
├── test.cpp
├── test.h
├── test.i
├── test.jar
├── test.o
├── test_wrap.cxx
└── test_wrap.o
3 directories, 20 files
1、环境准备
- 安装swig
ubuntu下可通过以下命令直接安装SWIG
sudo apt-get install swig
- 安装javaJDK
选择linux下x64版本deb安装包,下载后直接双击安装即可。
https://www.oracle.com/java/technologies/javase-jdk14-downloads.html - 安装javac命令
在命令行界面输入javac后,若没有安装javac,则会提示你需要安装
$ javac
The program 'javac' can be found in the following packages:
* openjdk-6-jdk
* ecj
* gcj-4.4-jdk
* gcj-4.6-jdk
* gcj-4.5-jdk
* openjdk-7-jdk
输入
sudo apt install openjdk-7-jdk
验证是否安装成功:
javac --version
2、swig封装文件准备
新建swigtest文件夹,并在文件夹下新建test.h、test.cpp、test.i文件。同时新建temp文件夹、com/test文件夹
- test.h文件内容如下
#include <string>
#include <vector>
int add(int a,int b);
std::string getString();
void setString(std::string str);
void setStrings(std::vector<std::string>& strList);
- test.cpp文件内容如下
#include "test.h"
int add(int a, int b)
{
return a+b;
}
std::string getString()
{
return "Hello world!";
}
void setString(std::string str)
{
}
void setStrings(std::vector<std::string>& strList)
{
}
- test.i文件内容如下
%module test
%{
#include "test.h"
%}
%include "std_string.i"
%include "std_vector.i"
%include "test.h"
namespace std{
%template(StrVector) vector<string>;
%template(IntVector) vector<int>;
%template(DoubleVector) vector<double>;
}
c++中STL与swig中对应关系如下图所示:
3、开始封装jar和so包
- 执行如下命令,会在当前目录下生成 test_wrap.cpp文件,在temp文件夹下生成对应的java文件
swig3.0 -c++ -java -package com.test -outdir ./temp -o test_wrap.cpp ./test.i
命令解释:
-package 指定生成java文件的包名称
-outdir 指定生成java文件路径
-o 指定生成的c++对外接口文件
- 编译temp下所有java文件为class文件
javac ./temp/*.java
- 移动生成的.class文件到com/test文件夹下
mv ./temp/*.class ./com/test
4.封装成jar包
jar -cvf test.jar ./com
至此jar包已经封装成功。接下来封装.so包
- 首先生成.o文件
gcc -c -fPIC test.cpp test_wrap.cpp -I/usr/lib/jvm/jdk-14.0.1/include -I/usr/lib/jvm/jdk-14.0.1/include/linux
注意:因为test_wrap.cpp中需要用到jni.h和jin_md.h,所以需要把其对应的路径包含进来。我的为安装jdk后的路径:
/usr/lib/jvm/jdk-14.0.1/include
/usr/lib/jvm/jdk-14.0.1/include/linux
- 连接.o文件为so动态库
gcc -shared -o libtest.so test.o test_wrap.o
4、运行demo
- 在swigtest下新建demo.java文件如下
import com.test.*;
class demo{
static {
//System.load("/home/weibaox/xwb/swigtest/libtest.so");
System.loadLibrary("test"); //刚才生成的libtest.so动态库。
}
public static void main(String argv[]){
int i = test.add(1,2);
System.out.println(i);
System.out.println(test.getString());
StrVector strvector;
test.setStrings(strvector);
}
}
- 把libtest.so所在路径设置到环境变量,以免运行时提示找不到test库,此处设置当前路径到环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
3.编译demo.java文件
javac -cp ./test.jar demo.java
-cp 指定demo.java依赖的jar包
4.执行生成的demo
java demo