JNI开发流程

预编译

C语言执行的流程

1.编译:形成目标代码(.obj)

2.连接:将目标代码与C函数库连接合并,形成最终的可执行文件

3.执行

预编译(预处理),为编译做准备工作,完成代码文本的替换工作

头文件告诉编译器有这样一个函数,连接器负责找到这个函数的实现

头文件只包含一次,防止重复引用:
1.#ifndef #define #endif组合使用(老版本)
2.#pragma once

define指令

1.定义标示

ifdef __cplusplus 标识支持C++语法

防止文件重复引入

2.定义常数(便于修改与阅读)

define MAX 100

3.定义“宏函数”

define jni(NAME) dn_com_jni_##NAME();NAME是参数,对于dn_com_jni_read函数来说,NAME就是read

//webrtc JNI函数名称很长,也是JOW宏函数缩短函数名称

void dn_com_jni_read(){
}

JNI(Java Native Interface)(Windows下)

Java调用C/C++,C/C++调用Java的一套API

1.编写native方法

2.javah命令,生成.h头文件。

3.复制.h头文件到CPP工程中

4.复制jni.h和jni_md.h文件到CPP工程中(去jdk安装目录里可以找到这两个.h文件)

5.实现.h头文件中声明的函数(C的函数名称:Java_完整类名_函数名)

#include "jni.h"
/* Header for class com_ccg_jni_JniTest */

#ifndef _Included_com_ccg_jni_JniTest
#define _Included_com_ccg_jni_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_ccg_jni_JniTest
 * Method:    getStringFromC
 * Signature: ()V
 */
JNIEXPORT jstring JNICALL Java_com_ccg_jni_JniTest_getStringFromC
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

C语言

#include "com_ccg_jni_JniTest.h"

//函数实现
JNIEXPORT jstring JNICALL Java_com_ccg_jni_JniTest_getStringFromC
(JNIEnv *env, jclass jcls){
    //JNIEnv 结构体指针
    //env二级指针
    //代表Java运行环境,调用Java中的代码

    //简单的实现
    //将C的字符串转为一个java字符串
    return (*env)->NewStringUTF(env,"C String");
}

C++

#include "com_ccg_jni_JniTest.h"
JNIEXPORT jstring JNICALL Java_com_ccg_jni_JniTest_getStringFromC
(JNIEnv *env, jclass jcls){
    //JNIEnv 在C++中就是一个结构体的别名
    //env 在C++中一个结构体的一级指针
    return env->NewStringUTF("C String");
}

6.生成dll文件(动态库,最终文件不包含动态库,.a静态库包含在最终文件里)

7.配置dll文件所在目录到环境变量(或者copy到工程根目录下)

8.重启Eclipse

分析JNIEnv

在C中:
JNIEnv 结构体指针别名
env二级指针

在C++中:
JNIEnv 是一个结构体的别名
env 一级指针

1.为什么需要传入JNIEnv,函数执行过程中需要JNIEnv
2.C++为什么没有传入? 因为C++this就代表了JNIEnv
3.C++只是对C的那一套进行的封装,给一个变量赋值为指针,这个变量是二级指针(把指针赋值给指针)

简写JNIEnv


//JNIEnv结构体的指针别名
typedef struct JNINativeInterface_* JNIEnv;

//结构体
struct JNINativeInterface_ {
    char* (*NewStringUTF)(JNIEnv*, char*);
};

//函数实现
char* NewStringUTF(JNIEnv* env, char* str){
    //在NewStringUTF执行过程,仍然需要JNIEnv
    return str;
}

void main(){
    //实例化结构体
    struct JNINativeInterface_ struct_env;
    struct_env.NewStringUTF = NewStringUTF;

    //结构体指针
    JNIEnv e = &struct_env;
    
    //结构体的二级指针
    JNIEnv *env = &e;

    //通过二级指针调用函数
    char* str = (*env)->NewStringUTF(env,"abc");
}

    

你可能感兴趣的:(JNI开发流程)