前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jni基础

jni基础

作者头像
曾大稳
发布2018-09-11 10:54:35
6980
发布2018-09-11 10:54:35
举报
文章被收录于专栏:曾大稳的博客曾大稳的博客

JNI 的一般开发流程

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

生成的 .h 文件参数详解

代码语言:javascript
复制
/* 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

实现类详解

代码语言:javascript
复制
// 实现我们的 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里面有如下代码

代码语言:javascript
复制
/*
 * 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;
    //  .... 
    }

在实现的函数里面

代码语言:javascript
复制
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流程

代码语言:javascript
复制
#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();
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档