android NDK开发学习之Jni(一)

JNI允许Java代码与其他编程语言如C/C++进行交互,常用于高效计算和实时应用。在AndroidStudio中,开发者可以创建C++工程来实现JNI功能,通过特定的签名规则调用和被调用。JNI的关键函数包括NewStringUTF、GetObjectClass等,调用时需遵循特定的命名规则。
摘要由CSDN通过智能技术生成

JNI是什么?

JNI即 java native interface,是jdk里边的一部分属于java内容,主要确保java 与 native层(C/C++)通信。C/C++一般用于高效率的数学运算、游戏的实时渲染、音视频编码解码等。

此时需要通过jni进行转换。

例如:java层中的变量 String name = "王六";

        Jni层 jstring name = "王六";

        c/c++层 char * name = "王六";

Jni的调用类似java的反射调用。

签名规则

C/C++调用java类对象的属性/方法 的 签名规则

常用规则如下:

java类型----------属性类型符号

boolean----------Z

byte----------B

char----------C

short----------S

int----------I

long----------J

float----------F

double----------D

void----------V

object----------L完整的类名;

method(参数类型)返回值类型 ---------- "java": void name(int a,double b) "c++": (ID)V 其中(ID)表示入参的两个类型

可通过javap获取class文件的对应签名类型

android studio 开发jni开发

1、创建C++ 工程 

2、导入C/C++文件

3、java/kotlin加载C/C++代码

 

 

调用规则

c++文件

native.cpp

#include <jni.h>
#include <string>

//extern "C" :下边的代码采用C的编译方式
//JNIEXPORT:JNI重要标记关键字,不能少(VS编译能通过,运行会报错) / (AS 运行不会报错), 规则(标记为该方法可以被外部调用) Windows内部规则,与Linux内部规则 不同
//jstring:代表 java 中的 String
//JNICALL :  也是一个关键字,(可以少的) jni call (约束函数入栈顺序,和堆栈内存清理的规则)
//jobject:  java传递下来的对象,就是本项目中 MainActivity 对象

extern "C" JNIEXPORT jstring JNICALL
// 规则:
//Java_包名(以_连接,如果原包名中有下划线则表示1)_类名_方法名
Java_com_wangyb_c_1xiangxue_1project_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    // 如果是c文件 native-lib.c
    //JNIEnv* env 是二级指针,使用时需要通过(*env)-> 调用
    return env->NewStringUTF(hello.c_str());
}


//jclass :java传递下来的 class 对象,就是本项目中的 MainActivity class
extern "C" JNIEXPORT void JNICALL
Java_com_wangyb_c_1xiangxue_1project_MainActivity_changeName(JNIEnv* env,jobject obj) {
    // 如果是c++文件 native-lib.cpp
    //JNIEnv* env 是一级指针,使用时可直接调用env->,调用原理如下
    // 1.修改name
    jclass mainActivityCls = env->GetObjectClass(obj);
    jfieldID name_fid = env->GetFieldID(mainActivityCls, "name","Ljava/lang/String;");
    jstring value = env->NewStringUTF("李老八");
    env->SetObjectField(obj, name_fid, value);
    //如果在c中,c是没有对象的,想持有env环境必须传入进去
    jstring value = (*env)->NewStringUTF(env,"李老八");
}

c文件

native.c

#include <jni.h>
//#include <string>

//extern "C" :下边的代码采用C的编译方式
//JNIEXPORT:JNI重要标记关键字,不能少(VS编译能通过,运行会报错) / (AS 运行不会报错), 规则(标记为该方法可以被外部调用) Windows内部规则,与Linux内部规则 不同
//jstring:代表 java 中的 String
//JNICALL :  也是一个关键字,(可以少的) jni call (约束函数入栈顺序,和堆栈内存清理的规则)
//jobject:  java传递下来的对象,就是本项目中 MainActivity 对象

//extern "C"
JNIEXPORT jstring JNICALL
// 规则:
//Java_包名(以_连接,如果原包名中有下划线则表示1)_类名_方法名
Java_com_wangyb_c_1xiangxue_1project_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject obj) {
//    std::string hello = "Hello from C++";
    // 如果是c文件 native-lib.c
    //JNIEnv* env 是二级指针,使用时需要通过(*env)-> 调用
    return (*env)->NewStringUTF(env,"Hello from C++");
}


//jclass :java传递下来的 class 对象,就是本项目中的 MainActivity class
//extern "C"
JNIEXPORT void JNICALL
Java_com_wangyb_c_1xiangxue_1project_MainActivity_changeName(JNIEnv* env,jobject obj) {
    // 如果是c++文件 native-lib.cpp
    //JNIEnv* env 是一级指针,使用时可直接调用env->
    // 1.修改name
    jclass mainActivityCls = (*env)->GetObjectClass(env,obj);
    jfieldID name_fid = (*env)->GetFieldID(env,mainActivityCls, "name","Ljava/lang/String;");
    jstring value = (*env)->NewStringUTF(env,"李老八");
    (*env)->SetObjectField(env,obj, name_fid, value);
}

原理

jni.h文件中


struct _JNIEnv;
struct _JavaVM;
typedef const struct JNINativeInterface* C_JNIEnv;

//此处表示是c++
#if defined(__cplusplus)
//JNIEnv是别名,所以JNIEnv* env是一级指针
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
//此处表示c 。JNINativeInterface* JNIEnv是一个一级指针。所以JNIEnv* env是二级指针(形参 *xxx 已经是一个二级指针了),调用时需要(*env)
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif


struct _JNIEnv {
    /* do not rename this; it does not seem to be entirely opaque */
    const struct JNINativeInterface* functions;

查看 手机设备cpu架构 adb命令

adb shell getprop ro.product.cpu.abi

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值