JNI开发摘要

概述

JNI开发主要是java层与c层的事件交互与数据互通,所有接口均在jni.h中可以找到,头文件可以在ndk开发包中找到,如:platforms/android-21/arch-arm64/usr/include/jni.h,在引用的时候可以直接#include<jni.h>.

java层代码特殊关键字native

对于jni接口,java层代码的接口必须添加关键字native,如下HelloWorld.java:

public class HelloWorld{

 static {
		System.loadLibrary("helloWorld"); //加载helloWorld.so
		//System.load("/system/lib/helloWorld.so"); //绝对路径加载
	}
	
	//这个接口测试c反调java代码 c/c++ -> java
	static void msgFromJNI(String str){
		Log.d("test", "this message is from jni : " + str);
	}
	
	//给外部使用的接口
	public void show(){
		print();
	}
	
	//jni接口 java-> c/c++
	private native void print();
}

C/C++层代码逻辑

注意c和c++在使用方式上基本一样,但是稍微有点区别是,很多接口参数上c++在使用env时,在参数上是省略了本身的,例如获取class对象:
c代码

(*env)->FindClass(env,className)

c++代码:

env->FindClass(className);

但是逻辑和使用基本一致不受影响.详细可以查看jni.h头文件的定义就很明了了.后续例子代码均采用c++编译,helloWorld.cpp

通过jni规定的接口名称进行映射java接口(我称作为静态接口)

#include <jni.h>
/*
 * Class:     com.example.HelloWorld
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT jboolean JNICALL Java_com_example_HelloWorld_print
        (JNIEnv *env, jclass obj){
    printf("Hello world\n");
}

上面这种方式就可以直接使用了,当编译成helloWorld.so之后,由HelloWorls.java去静态加载,之后就可以正常使用print 本地c++接口了.

动态注册jni接口

这种方式java部分代码不用改变.c/c++代码中不用按照特定的java代码中的包名_类名_接口名等规定样式编写接口,而且可以动态的注册和取消接口注册

#include <jni.h>

typedef struct
{
    JavaVM *VM;   //java虚拟机实例
    jclass helloWorldCls; //用来存储java中HelloWorld对象
    jmethodID  msgFromJNI; //存储java中msgFromJNI方法id,调用接口时会用到
} helloWorld_t;

//这个是要注册的native接口,这里目前只注册了print.
//需要注册多个时,继续添加即可
/*
*第一参数:java上定义的jni接口名称
*第二个参数:方法标签,表示接口的参数和返回值()内部的表示参数,()外面的是返回值
*Ljava/lang/Object;代表的是字符串,V代表是void
*第三个参数函数指针,也就是对应调用的c函数
*/
static const JNINativeMethod gMethods[] = {
        {"print", "(Ljava/lang/Object;)V", (void*)__print},
};

static helloWorld_t stHelloWorld;
static const char * HelloWorldClassName = "com.example.HelloWorld"
void regist_helloWorld(JNIEnv* env){
    if(!env){
        return JNI_FALSE;
    }
    //存储一下jvm
    if(JNI_OK != env->GetJavaVM(&stHelloWorld.VM)){
        return JNI_FALSE;
    }
    //获取class对象,你可以理解为java反射机制,通过包名类名获取classz.
	stHelloWorld.helloWorldCls = env->FindClass(HelloWorldClassName);
	//由于我们后续会一直使用这个class,这里需要保存为global全局对象,以便本次线程结束之后无法再次使用.
	 stHelloWorld.helloWorldCls  = (jclass)env->NewGlobalRef(stHelloWorld.helloWorldCls);
	 if(NULL ==stHelloWorld.helloWorldCls)
	 {
	 	return JNI_FAILE;
	 }
	//获取msgFromJNI方法id
	stHelloWorld.msgFromJNI =  env->GetStaticMethodID(stHelloWorld.helloWorldCls "msgFromJNI", "(Ljava/lang/Object;)V");
	
	//注册native接口,第一个参数注册的类,第二个参数:注册的方法列表,第三个参数方法数
	 if (env->RegisterNatives(stHelloWorld.helloWorldCls , gMethods, sizeof(gMethods)/sizeof(JNINativeMethod)) < 0)
    {
        return JNI_FALSE;
    }
	//以上完成了函数注册还有存储了一个java方法的id(msgFronJNI).
}

/*
*so被加载时被系统回调的第一个接口,我们可以在这个接口中通过jni.h的接口去注册本地方法
*/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){
    jint result = -1;
    JNIEnv* env = NULL;
    if((vm)->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
        return result;
    regist_helloWorld(env);
    printf("--------JNI_OnLoad-----SUCCESS");
    return JNI_VERSION_1_4; //这里很重要,必须返回版本,否则加载会失败。
}

static void JNICALL __print(JNIEnv *env, jobject jobj, jstring userid)
{
    bool bRet = false;
    const char* p8Userid = env->GetStringUTFChars(userid, 0);
    if(!p8Userid){
        return bRet;
    }
   printf("%s\n", p8Userid);
   //这里我们主动释放内存
   env->ReleaseStringUTFChars(userid, p8Userid);

//这里我们直接测试反调用HelloWorld.java里面的msgFromJNI方法.
char * testString = "I'm c string";
jstring jsr = env->NewStringUTF(testString);
//调用java中的msgFromJNI方法
env->CallStaticVoidMethod(stHelloWorld.helloWorldCls, stHelloWorld.msgFromJNI , jstr);
//使用完jstr之后,我们进行回收
env->ReleaseStringUTFChars(jstr, testString);
//这样我们简单完成了java->c/c++, 以及c/c++->java的流程了.
return bRet;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值