jni基础

JNI 的一般开发流程

1 定义好本地的 native 方法 2 javah 命令生成 .h 头文件 3 拷贝 xxx.h、jni_md.h、jni.h 到 VS 的工程目录并添加依赖进来 4 实现我们头文件中的 native 方法 5 生成 dll 动态,java 引入 dll 动态库运行即可

生成的 .h 文件参数详解

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"// "" 引入自己工程的头文件 <> 引入系统的头文件
/* Header for class com_darren_ndk12_NdkSimple */
// 用来打一个标记,c在编译的时候会把头文件 copy 到你引入的地方,不管是重复引用还是相互引用都只会 copy 一次
#ifndef _Included_com_darren_ndk12_NdkSimple
#define _Included_com_darren_ndk12_NdkSimple
#ifdef __cplusplus // 相当于 if 语句 c++ 
// 不管是 c 还是 c++ 统一都是采用 c 的编译方式,因为在c里面是不允许函数重载的,但是在 c++ 里面可以
extern "C" {
#endif
/*
 * Class:     com_darren_ndk12_NdkSimple
 * Method:    getSingnaturePassword
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_darren_ndk12_NdkSimple_getSingnaturePassword
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

实现类详解

// 实现我们的 native 方法
#include "com_darren_ndk12_NdkSimple.h"

// JNIEXPORT JNI 一个关键字,不能少(编译能通过),标记为该方法可以被外部调用
// jstring : 代表 java 中的 String 
// JNICALL: 也是一个关键字,可以少的 jni call
// JNIEnv: 这个是 c 和 java 相互调用的桥梁,所有 function 搞清
// jobject: java传递下来的对象,就是本项目中 JniSimple java 对象
// jclass: 静态函数的时候java传递下来的 class 对象,就是本项目中的 JniSimple.class 
JNIEXPORT jstring JNICALL Java_com_darren_ndk12_NdkSimple_getSingnaturePassword
(JNIEnv * env, jobject jobj){
	// JNIEnv * 其实已经是一个二级指针了,所以 -> 调用的情况下必须是一级指针 *取值 
	return (*env)->NewStringUTF(env,"940223");
}

JNIEnv是什么

jni.h里面有如下代码

/*
 * JNI Native Method Interface.
 */

struct JNINativeInterface_;

struct JNIEnv_;


#ifdef __cplusplus  //如果是c++就是JNIEnv_对象 JNIEnv_对象里面其实也是通过JNINativeInterface_调用
typedef JNIEnv_ JNIEnv;
#else  //如果是c的话就是JNINativeInterface_指针
typedef const struct JNINativeInterface_ *JNIEnv;
#endif



struct JNIEnv_ {
    const struct JNINativeInterface_ *functions;
    //  .... 
    }

在实现的函数里面

JNIEXPORT jstring JNICALL Java_com_darren_ndk12_NdkSimple_getSingnaturePassword
(JNIEnv * env, jobject jobj){
	// JNIEnv * 其实已经是一个二级指针了,所以 -> 调用的情况下必须是一级指针 *取值 
	return (*env)->NewStringUTF(env,"940223");
}

所以为什么在c里面调用函数需要用(*env)-> ,而c++只需要用env->

JNIEnv流程

手写JNIEnv流程

#include <stdlib.h>
#include <stdio.h>
// 定义一个结构体指针的别名
typedef const struct JNINativeInterface *JNIEnv;
// 模拟一个结构体
struct JNINativeInterface{
	// 结构体的方法指针
	char*(*NewStringUTF)(JNIEnv*,char*);
};

char* NewStringUTF(JNIEnv* env, char* c_str){
	// c_str -> jstring
	return c_str;
}

char* Java_com_darren_getSingnaturePassword(JNIEnv * env){
	// JNIEnv * 其实已经是一个二级指针了,所以 -> 调用的情况下必须是一级指针 *取值 
	return (*env)->NewStringUTF(env, "940223");
}

void main(){

	// 构建 JNIEnv* 对象
	struct JNINativeInterface nativeInterface;
	// 给结构方法指针进行复制(实现)
	nativeInterface.NewStringUTF = NewStringUTF;

	// 传给 Java_com_darren_ndk12_NdkSimple_getSingnaturePassword 的参数是 JNIEnv*
	JNIEnv env = &nativeInterface;// 一级指针
	JNIEnv* jniEnv = &env;// 二级指针

	// 把 jniEnv 对象传给 Java_com_darren_ndk12_NdkSimple_getSingnaturePassword
	char* jstring = Java_com_darren_getSingnaturePassword(jniEnv);

	// jstring 通过 JNIEnv 传给 java 层
	printf("jstring = %s",jstring);

	getchar();
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏iOS开发

iOS开发之 Method Swizzling 深入浅出

如果产品经理突然说:"在所有页面添加统计功能,也就是用户进入这个页面就统计一次"。我们会想到下面的一些方法:

49370
来自专栏ppjun专栏

RecyclerView 缓存策略

37940
来自专栏jeremy的技术点滴

JVM的Finalization Delay引起的OOM

43280
来自专栏JavaEdge

Netty源码阅读入门实战(八)-解码(更新 ing)

就像很多标准的架构模式都被各种专用框架所支持一样,常见的数据处理模式往往也是目标实现的很好的候选对象,它可以节省开发人员大量的时间和精力。 当然这也适应于本文...

15340
来自专栏IMWeb前端团队

Nodejs基础:巧用string_decoder将buffer转成string

本文作者:IMWeb 陈映平 原文出处:IMWeb社区 未经同意,禁止转载 模块简介 string_decoder模块用于将Buffer转成对应的字符...

20860
来自专栏ppjun专栏

ViewModel 源码分析

从图可以看出来,ViewModel 与 LiveData 和 Paging 是谷歌新组件,同时它是 android.arch.lifecycle 包里面的类,可...

18310
来自专栏Android 研究

OKHttp源码解析(五)--OKIO简介及FileSystem

okio是由square公司开发的,它补充了java.io和java.nio的不足,以便能够更加方便,快速的访问、存储和处理你的数据。OKHttp底层也是用该库...

28430
来自专栏恰童鞋骚年

Hadoop学习笔记—7.计数器与自定义计数器

  在上图所示中,计数器有19个,分为四个组:File Output Format Counters、FileSystemCounters、File Input...

12220
来自专栏冰霜之地

高效的序列化/反序列化数据方式 Protobuf

上篇文章中其实已经讲过了 encode 的过程,这篇文章以 golang 为例,从代码实现的层面讲讲序列化和反序列化的过程。

67050
来自专栏Android 研究

APK安装流程详解5——Installer、InstallerConnection和Installd守护进程

因为Installer继承自SystemService,所以我们看下Installer的onStart方法 代码在Installer.java 396行

18310

扫码关注云+社区

领取腾讯云代金券