c++生成java接口,jni技术

24 篇文章 1 订阅
13 篇文章 0 订阅

c++ 生成java 接口最本质的方法是通过jni 技术,jni 技术可以实现java 和c++的互相调用
那么生成so 具体用什么方法好呢?
我所知道的有四种方式
1: 写andorid 的android.mk 文件,之前在eclipse 中使用过,mk 文件就相当于Makefile
2: SWIG 技术,一个工具,c++ 语言生成各种其他语言的工具,java,c#,python 等都支持,中文文档太少,没研究明白
3:创建交叉工具链,在linux 上写Makefile 的方式,推荐此方法,因为和写Makefile 一样,只是工具链换了
4:创建交叉工具链,和三一样,只是要写cmakelist.txt, 和三差不多啦
本文介绍一下如何用第三个方法生成so

1:安装jdk, eclipse 或者 android studio
eclipse 和 android studio 是为测试so 用的
2:设计一个接口比如:我是用eclipse 先创建一个工程java0,然后在src 下面创建一个包com.faceos.jni, 然后又创建一个InterfaceJNI.java 类
之所以创建一个包方便最后打包, 创建方式都是右键->new

package com.faceos.jni;
public class InterfaceJNI {
	 public final static native int add(int a, int b);
	  public final static native String getString(byte[] byteArray);
	 static 
	 {
		 System.out.println("load interface");
		 System.loadLibrary("Interface");
		 System.out.println("load interface");
	 }	
}

目录结构
在这里插入图片描述
2: 需要用javah 命令生成c++ 的头文件
编译一下啊,就会在java0 目录下生成InterfaceJNI.class 文件
在java0 文件下开一个终端
javah javah -classpath ./bin -d ./cpp -jni com.faceos.InterfaceJNI
就会在当前目录下的cpp 文件夹下生成一个头文件,如果不成功,可能是你需要先新建一个cpp 文件夹

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_faceos_jni_InterfaceJNI */

#ifndef _Included_com_faceos_jni_InterfaceJNI
#define _Included_com_faceos_jni_InterfaceJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_faceos_jni_InterfaceJNI
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_faceos_jni_InterfaceJNI_add
  (JNIEnv *, jclass, jint, jint);

/*
 * Class:     com_faceos_jni_InterfaceJNI
 * Method:    getString
 * Signature: ([B)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_faceos_jni_InterfaceJNI_getString
  (JNIEnv *, jclass, jbyteArray);

#ifdef __cplusplus
}
#endif
#endif

这就是生成的头文件
在cpp 文件下面创建一个InterfaceJNI.cpp
实现上面连个函数的功能

#include "com_faceos_jni_InterfaceJNI.h"

#include <android/log.h>
#define TAG "InterfaceJNI"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)

extern "C"
{
JNIEXPORT jint JNICALL Java_com_faceos_jni_InterfaceJNI_add
  (JNIEnv *env, jclass obj, jint a, jint b)
{
	LOGE("########### a = %d b = %d \n", a, b);
	return a + b;
}
JNIEXPORT jstring JNICALL Java_com_faceos_jni_InterfaceJNI_getString
  (JNIEnv *, jclass, jbyteArray)
{
	return 0;
}

}

接下来就需要编译出来libInterface.so
如何编译呢

2.1:创建交叉工具编译链
下载android-ndk-r16b-linux-x86_64.zip ,那个网站自己搜
unzip android-ndk-r16b-linux-x86_64.zip 解压出来
cd /android-ndk-r16b/build/tools
这个目录
生成 arm64 toolchain: 请执行下面命令
./make_standalone_toolchain.py --arch arm64 --api 21 --install-dir /home/zl/share/toolchain/aarch64-linux-android

生成 arm32 toolchain: 请执行下面命令
./make_standalone_toolchain.py --arch arm --api 21 --install-dir /home/zl/share/toolchain/arm-linux-androideabi

生成目录替换成自己指定的目录
如此工具链就生成好了
2.2 在cpp 文件夹下写一个Makefile_armeabi 文件


Target:=libInterface.so
LIBS +=	
AFLAGS := -Wall -c -fPIC -O2 -std=c++11 $(INCS)
LDFLAGS := -llog
#LDFLAGS += -Wl,-rpath, 
OBJS := $(patsubst %.cpp,%.o,$(shell find . -name "*.cpp"))
all: $(Target)
$(Target): $(OBJS)
	$(CC) -shared -o $@ $^ $(LDFLAGS) $(LIBS)
$(OBJS): %.o:%.cpp
	$(CC) $(AFLAGS) $^ -o $@
debugOBJS:
	@echo ${OBJS}
.PHONY: clean FaceFilter setenv
clean:					
	rm -rf *.o *.so 

2.3 在cpp 文件下创建一个armeabi.sh 脚本文件

export PATH=/home/zl/share/toolchain/arm-linux-androideabi/bin:$PATH

# Tell configure what tools to use.
target_host=arm-linux-androideabi
export AR=$target_host-ar
export AS=$target_host-clang
export CC=$target_host-clang
export CXX=$target_host-clang++
export LD=$target_host-ld
export STRIP=$target_host-strip

# Tell configure what flags Android requires.
export CFLAGS="-fPIE -fPIC"

make -f Makefile_armeabi clean
make -f Makefile_armeabi all

ok 脚本写好了,稍微解释一下export 配置一下环境
2.4 执行脚本
./armeabi.sh
顺利生成libInterface.so
3: 接下来就是测试这个so啦
把so 拷贝到工程路径下,android studio 在main 文件夹下新建jniLibs/armeabi 文件夹
如果是64位jniLibs/arm64-v8a
把库拷进去, 在main 函数中调用

 int ret =  InterfaceJNI.add(10, 20);
      System.out.println("ret = " + ret);

结果正确大功告成,如果想传输比较复杂的数据,如数组可以参考
https://blog.csdn.net/baidu_31872269/article/details/83151831
如有问题 791668193@qq.com 联系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值