Linux下SWIG封装c++接口供java使用

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、环境准备

  1. 安装swig
    ubuntu下可通过以下命令直接安装SWIG
sudo apt-get install swig
  1. 安装javaJDK
    选择linux下x64版本deb安装包,下载后直接双击安装即可。
    https://www.oracle.com/java/technologies/javase-jdk14-downloads.html
  2. 安装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文件夹

  1. test.h文件内容如下
#include 
#include 
int add(int a,int b);
std::string getString();
void setString(std::string str);
void setStrings(std::vector<std::string>& strList);
  1. 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)
{
}
  1. 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中对应关系如下图所示:
Linux下SWIG封装c++接口供java使用_第1张图片

3、开始封装jar和so包

  1. 执行如下命令,会在当前目录下生成 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++对外接口文件

  1. 编译temp下所有java文件为class文件
javac ./temp/*.java
  1. 移动生成的.class文件到com/test文件夹下
mv ./temp/*.class ./com/test

4.封装成jar包

 jar -cvf test.jar ./com

至此jar包已经封装成功。接下来封装.so包

  1. 首先生成.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

  1. 连接.o文件为so动态库
gcc -shared -o libtest.so test.o test_wrap.o

4、运行demo

  1. 在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);
	}
}
  1. 把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

你可能感兴趣的:(c++)