Android开发,JNI,NDK,C++层操作java的对象实践

news2024/11/18 7:52:02

Android开发,JNI,NDK,C++层操作java的对象实践

1.数组

在jni中调用数组

extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testArr(JNIEnv *env, jobject thiz, jint a, jstring s,
                                                    jintArray ints, jobjectArray strings) {
    int cnt = a;
    LOGD("cnt == %d\n", cnt);
    const char *test = env->GetStringUTFChars(s, NULL);
    LOGD("------ %s\n", test);
    //回收
    env->ReleaseStringUTFChars(s, test);
}

在这里插入图片描述

运行下

在这里插入图片描述

遍历int数组在jni中

在这里插入图片描述

jni修改数组底层,JNI_OK标记

在这里插入图片描述

在这里插入图片描述

java层随之改变

在这里插入图片描述

2.引用数据类型数组

字符串类型数组在jni中

在这里插入图片描述

修改java层

在这里插入图片描述

jni代码

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

#include <android/log.h>

#define TAG "testLog"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
//代码采用C语言编译
extern "C"
//关键字jni,
JNIEXPORT
//java的native方法的返回值
void
//关键字
JNICALL
//java包名, 类名,方法名
//jobject1是MainActivity的this实例
//一个是类调用,一个是对象调用,
Java_com_example_myapplication_MainActivity_test(JNIEnv *env, jobject jobject1) {


}extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_doubleFromJNI(JNIEnv *env, jobject thiz) {
    jclass test = env->GetObjectClass(thiz);
//    jfieldID num = env->GetFieldID(test, "num", "D");
//
//    env->SetDoubleField(thiz,num, 444.5);


    jfieldID num2 = env->GetFieldID(test, "num2", "D");
    env->SetDoubleField(thiz, num2, 5555.5);

    LOGD("SSSSSSSSSSSSSS %d\n", 1312);
}extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testAddNum(JNIEnv *env, jobject thiz) {
    /*jclass jclass1 = env->GetObjectClass(thiz);
    jmethodID add = env->GetMethodID(jclass1, "addNum", "(II)I");
    int jint = env->CallIntMethod(thiz, add, 2, 3);
    LOGD("============%d\n", jint);*/
    jclass jclass1 = env->GetObjectClass(thiz);
    jmethodID jmethodId = env->GetMethodID(jclass1, "getTestString",
                                           "(Ljava/lang/String;I)Ljava/lang/String;");
    jstring va = env->NewStringUTF("22222");
    jstring rrr = (jstring) env->CallObjectMethod(thiz, jmethodId, va, 222);
    const char *string = env->GetStringUTFChars(rrr, NULL);
    LOGD("==============%s\n", string);
}extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testArr(JNIEnv *env, jobject thiz, jint a, jstring s,
                                                    jintArray ints, jobjectArray strings) {
    int cnt = a;
    LOGD("cnt == %d\n", cnt);
    const char *test = env->GetStringUTFChars(s, NULL);
    LOGD("------ %s\n", test);
    //回收
    env->ReleaseStringUTFChars(s, test);
    //获取java传下来的数组
    jint *jint1 = env->GetIntArrayElements(ints, NULL);

    //计算长度
    int len = env->GetArrayLength(ints);
    for (int i = 0; i < len; ++i) {
        LOGD("C++ %d\n", *(jint1 + i));
        *(jint1 + i) = (i + 10111);
    }
    //释放素组内存,jni下面的修改传递给java层
    env->ReleaseIntArrayElements(ints, jint1, JNI_OK);

    //
    int strslen = env->GetArrayLength(strings);
    for (int i = 0; i < strslen; ++i) {
        jstring jstring1 = (jstring) env->GetObjectArrayElement(strings, i);
        const char *string = env->GetStringUTFChars(jstring1, NULL);
        LOGD("C++============ %s\n", string);
        //释放内存
        env->ReleaseStringUTFChars(jstring1,string);
        //修改java层
        jstring updateValue = env->NewStringUTF("qiuqiuqiuqiuq");
        env->SetObjectArrayElement(strings, i, updateValue);

        jstring jstring12 = (jstring) env->GetObjectArrayElement(strings, i);
        const char *string2 = env->GetStringUTFChars(jstring12, NULL);
        LOGD("C++============2222 %s\n", string2);


        //释放内存,jni函数结束会释放变量的内存
        env->ReleaseStringUTFChars(jstring12,string2);
    }

}

java代码

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
//        System.loadLibrary("native-lib");
        System.loadLibrary("native-lib");
    }

    private static final String TAG = "MainActivity";
    private String test = "test";

    public native String stringFromJNI();

    public native void test();

    private double num = 1;
    private double num2 = 2;

    public native void doubleFromJNI();

    //jni调用它
    public int addNum(int a, int b) {
        Log.e(TAG, "addNum: ");
        return a + b;
    }

    //
    public native void testAddNum();

    public String getTestString(String s, int a) {
        Log.e(TAG, "getTestString: ");
        return s;
    }

    public native void testArr(int a, String s, int[] ints, String[] strings);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
        Log.e(TAG, "onCreate: ");
        test();
        Log.e(TAG, "onCreate: 修改前 " + num2);
        doubleFromJNI();
        Log.e(TAG, "onCreate: 修改后 " + num2);
        testAddNum();
    }

    public void test1(View view) {
        int[] ints = new int[]{1, 2, 3};
        String[] strings = new String[]{"123", "1"};
        testArr(111, "222", ints, strings);
        for (int anInt : ints) {
            Log.e(TAG, "test1: anInt" + anInt);
        }
        for (String string : strings) {
            Log.e(TAG, "test1: string" + string);
        }
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
}

3.java对象,jni层创建java对象

java

package com.example.myapplication;

import androidx.annotation.NonNull;

public class Test {
    private static final String TAG = "Test";
    public String name;
    public int age;
    public Test() {
    }

    public Test(String a, int b) {
        this.name = a;
        this.age = b;
    }

    public static String getTAG() {
        return TAG;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Test{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

jni代码

extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testObject(JNIEnv *env, jobject thiz,
                                                       jobject test,
                                                       jstring cstring) {
    const char *string = env->GetStringUTFChars(cstring, NULL);
    LOGD("string ============== %s\n", string);
    //回收ziy
    env->ReleaseStringUTFChars(cstring, string);

    jclass jclass1 = env->FindClass("com/example/myapplication/Test");
    //调用对象的toString
    jmethodID toStringId = env->GetMethodID(jclass1, "toString", "()Ljava/lang/String;");

    jstring jstring1 = (jstring) env->CallObjectMethod(test, toStringId);

    const char *toStringJstring1 = env->GetStringUTFChars(jstring1, NULL);
    LOGD("toStringJstring1 ==== %s\n", toStringJstring1)
}

在这里插入图片描述

测试代码

  public void test2(View view) {
        Test test = new Test();
        test.name = "adasd";
        test.age = 111;
        testObject(test, "hello");
    }

jni中调用对象的get,set方法

extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testObject(JNIEnv *env, jobject thiz,
                                                       jobject test,
                                                       jstring cstring) {
    const char *string = env->GetStringUTFChars(cstring, NULL);
    LOGD("string ============== %s\n", string);
    //回收ziy
    env->ReleaseStringUTFChars(cstring, string);

    jclass jclass1 = env->FindClass("com/example/myapplication/Test");
    //调用对象的toString
    jmethodID toStringId = env->GetMethodID(jclass1, "toString", "()Ljava/lang/String;");

    jstring jstring1 = (jstring) env->CallObjectMethod(test, toStringId);

    const char *toStringJstring1 = env->GetStringUTFChars(jstring1, NULL);
    LOGD("toStringJstring1 ==== %s\n", toStringJstring1)
    //释放内存
    env->ReleaseStringUTFChars(jstring1, toStringJstring1);
    env->DeleteLocalRef(jclass1);

    jclass tesObj = env->FindClass("com/example/myapplication/Test");

    jmethodID setName = env->GetMethodID(tesObj, "setName", "(Ljava/lang/String;)V");
    jstring jstring2 = env->NewStringUTF("1123131");
    //调用对象的set方法
    env->CallVoidMethod(test, setName, jstring2);


    //调用get方法
    jclass tesObj1 = env->FindClass("com/example/myapplication/Test");

    jmethodID getName = env->GetMethodID(tesObj, "getName", "()Ljava/lang/String;");
    //调用对象的get方法
    jstring jstring3 = (jstring) env->CallObjectMethod(test, getName);
    const char *name = env->GetStringUTFChars(jstring3, NULL);
    LOGD("get name ==== %s\n", name)

}

运行

在这里插入图片描述

可以看出get,set方法都被调用,并且get到我们设置的值

jni创建对象

java

 public native void testCreateObj();

    public void test3(View view) {
        testCreateObj();
    }

jni

extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testCreateObj(JNIEnv *env, jobject thiz) {

    jclass jclass1 = env->FindClass("com/example/myapplication/Test2");
    jclass jclass2 = env->FindClass("com/example/myapplication/Test");
    //分配对象,不会调用构造方法
    jobject jobject1 = env->AllocObject(jclass1);
    jobject jobject2 = env->AllocObject(jclass2);

    //实例化对象
//    env->NewObject(jclass1);
        jmethodID jmethodId = env->GetMethodID(jclass1,"setTest",
                                               "(Lcom/example/myapplication/Test;)V");


    env->CallVoidMethod(jobject1,jmethodId,jobject2);


    jmethodID setName = env->GetMethodID(jclass2, "setName", "(Ljava/lang/String;)V");
    jstring jstring2 = env->NewStringUTF("2222222");
    //调用对象的set方法
    env->CallVoidMethod(jobject2, setName, jstring2);
}

运行在jni创建的对象,

在这里插入图片描述

4.全局对象引用

测试代码Test

package com.example.myapplication;

import android.util.Log;

import androidx.annotation.NonNull;

public class Test {
    private static final String TAG = "Test";
    public String name;
    public int age;

    public Test() {
        Log.e(TAG, "Test: ");
    }

    public Test(int num) {
        Log.e(TAG, "Test: " + num);
    }

    public Test(int num1, int num2) {
        Log.e(TAG, "Test: " + num1 + num2);

    }

    public static void testStatic(String info) {

    }

    public Test(String a, int b) {
        this.name = a;
        this.age = b;
    }

    public static String getTAG() {
        return TAG;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        Log.e(TAG, "setName: " + name);
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Test{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

MainActivity

public native void testGlobalReferences();

    public native void deleteGlobalReferences();

    @Override
    protected void onDestroy() {
        super.onDestroy();
        deleteGlobalReferences();
    }

    public void test4(View view) {
        testGlobalReferences();
    }

    public void test5(View view) {
        deleteGlobalReferences();
    }

jni调用java层的构造方法

extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testGlobalReferences(JNIEnv *env, jobject thiz) {

    if (!test) {
        test = env->FindClass("com/example/myapplication/Test");

    }
    //init 构造方法。()调用无参构造方法
    jmethodID jmethodId = env->GetMethodID(test, "<init>", "()V");
    jobject jobject1 = env->NewObject(test, jmethodId);
    //调用一个参数构造方法
    jmethodID jmethodId2 = env->GetMethodID(test, "<init>", "(I)V");
    jobject jobject2 = env->NewObject(test, jmethodId2, 1);
    //调用两个参数构造方法
    jmethodID jmethodId3 = env->GetMethodID(test, "<init>", "(II)V");
    jobject jobject3 = env->NewObject(test, jmethodId3, 1, 2);
}

测试

在这里插入图片描述

局部引用和全局引用

//是局部变量,自动释放内存
jclass test = nullptr;
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_deleteGlobalReferences(JNIEnv *env, jobject thiz) {
    if (!test) {
        env->DeleteGlobalRef(test);
        test = nullptr;
    }
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testGlobalReferences(JNIEnv *env, jobject thiz) {

    if (!test) {
//        test = env->FindClass("com/example/myapplication/Test");

        jclass jclass1 = env->FindClass("com/example/myapplication/Test");
        //全局变量
        test = (jclass) env->NewGlobalRef((jobject) jclass1);
        env->DeleteLocalRef(jclass1);
    }
    //init 构造方法。()调用无参构造方法
    jmethodID jmethodId = env->GetMethodID(test, "<init>", "()V");
    jobject jobject1 = env->NewObject(test, jmethodId);
    //调用一个参数构造方法
    jmethodID jmethodId2 = env->GetMethodID(test, "<init>", "(I)V");
    jobject jobject2 = env->NewObject(test, jmethodId2, 1);
    //调用两个参数构造方法
    jmethodID jmethodId3 = env->GetMethodID(test, "<init>", "(II)V");
    jobject jobject3 = env->NewObject(test, jmethodId3, 1, 2);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1298714.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Axure网页端高交互组件库, 下拉菜单文件上传穿梭框日期城市选择器

作品说明 组件数量&#xff1a;共 11 套 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;web端原型设计、桌面端原型设计 作品特色 本作品为「web端组件库」&#xff0c;高保真高交互 (带仿真功能效果)&#xff1b;运用了动态面板、中继…

LNMP网站架构分布式搭建部署

1. 数据库的编译安装 1. 安装软件包 2. 安装所需要环境依赖包 3. 解压缩到软件解压缩目录&#xff0c;使用cmake进行编译安装以及模块选项配置&#xff08;预计等待20分钟左右&#xff09;&#xff0c;再编译及安装 4. 创建mysql用户 5. 修改mysql配置文件&#xff0c;删除…

如何为游戏角色3D模型设置纹理贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时&#xff0c;有几种不同的风格&#xf…

【面试经典150 | 二叉树】从中序与后序遍历序列构造二叉树

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;递归 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容…

股票放量成交后,大涨的概率有多少?

很多时候&#xff0c;经常有人会感觉&#xff0c;成交量突然放大5倍以上&#xff0c;后面的股价大概率会上涨&#xff0c;很多投顾班的老师也是给大家展示这样的感觉&#xff0c;那究竟有多大比例的上涨呢&#xff1f; 【文章仅是数据分析&#xff0c;不构成任何投资建议】 一…

ROS gazebo 机器人仿真,环境与robot建模,添加相机 lidar,控制robot运动

b站上有一个非常好的ros教程234仿真之URDF_link标签简介-机器人系统仿真_哔哩哔哩_bilibili&#xff0c;推荐去看原视频。 视频教程的相关文档见&#xff1a;6.7.1 机器人运动控制以及里程计信息显示 Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 本文对视频教程…

工业4.0分类:数字化转型的多维度

引言 工业4.0代表着制造业的数字化革命&#xff0c;它将制造过程带入了数字时代。然而&#xff0c;工业4.0并不是一个单一的概念&#xff0c;而是一个多维度的范畴&#xff0c;包括不同的技术、应用领域、企业规模和实施方式。但在这一多维度的概念中&#xff0c;低代码技术正…

CSS新手入门笔记整理:CSS浮动布局

文档流概述 正常文档流 “文档流”指元素在页面中出现的先后顺序。正常文档流&#xff0c;又称为“普通文档流”或“普通流”&#xff0c;也就是W3C标准所说的“normal flow”。正常文档流&#xff0c;将一个页面从上到下分为一行一行&#xff0c;其中块元素独占一行&#xf…

【刷题】位运算

2 n 2^n 2n 1<<n判断某一位是否为1 s&1<<k将上面两个组合&#xff0c;可以得到判断一个集合中哪些内容包含&#xff0c;遍历所有情况。 100140. 关闭分部的可行集合数目 一个公司在全国有 n 个分部&#xff0c;它们之间有的有道路连接。一开始&#xff0c;…

网络攻击(二)--情报搜集阶段

4.1. 概述 在情报收集阶段&#xff0c;你需要采用各种可能的方法来收集将要攻击的客户组织的所有信息&#xff0c;包括使用社交网络、Google Hacking技术、目标系统踩点等等。 而作为渗透测试者&#xff0c;你最为重要的一项技能就是对目标系统的探查能力&#xff0c;包括获知…

kafka学习笔记--生产者消息发送及原理

本文内容来自尚硅谷B站公开教学视频&#xff0c;仅做个人总结、学习、复习使用&#xff0c;任何对此文章的引用&#xff0c;应当说明源出处为尚硅谷&#xff0c;不得用于商业用途。 如有侵权、联系速删 视频教程链接&#xff1a;【尚硅谷】Kafka3.x教程&#xff08;从入门到调优…

深度学习记录--神经网络表示及其向量化

神经网络表示 如下图 就这个神经网络图来说&#xff0c;它有三层&#xff0c;分别是输入层(Input layer)&#xff0c;隐藏层(Hidden layer)&#xff0c;输出层(Output layer) 对于其他的神经网络&#xff0c;隐藏层可以有很多层 一般来说&#xff0c;不把输入层算作一个标准…

Idea的Marketplace下载不了插件,idea下不了插件

Idea的Marketplace下载不了插件 解决方案&#xff08;配置代理&#xff09; 附一张成功界面 2.问题复现 3.问题原因和解决方式&#xff1a;下载安装IDEA之后HTTP Proxy没有进行相关配置的问题&#xff0c;解决方式如下 1.首先打开file->setting->Appearance & B…

【设计模式-4.4】行为型——模板方法模式

说明&#xff1a;本文介绍设计模式中行为型设计模式中的&#xff0c;模板方法模式&#xff1b; 生存 模版方法模式是行为型设计模式&#xff0c;关注于对象的行为。在《秒懂设计模式》&#xff08;刘韬 著&#xff09;中举了一个例子&#xff0c;例如哺乳动物的生存技能&…

【python交互界面】实现动态观察图像在给定HSV范围的区域显示

HSV颜色空间 与RGB颜色空间相比&#xff0c;HSV颜色空间更适合进行颜色分析和提取特定颜色的目标。在HSV空间中&#xff0c;颜色信息被分布在不同的通道上&#xff0c;使我们能够更准确地定义颜色的范围&#xff0c;并使用阈值操作轻松地分离出我们感兴趣的区域部分。 HSV三个通…

本地部署语音转文字(whisper,SpeechRecognition)

本地部署语音转文字 1.whisper1.首先安装Chocolatey2.安装3.使用 2.SpeechRecognition1.环境2.中文包3.格式转化4.运行 3.效果 1.whisper 1.首先安装Chocolatey https://github.com/openai/whisper 以管理员身份运行PowerShell Set-ExecutionPolicy Bypass -Scope Process -…

VoxPoser:使用语言模型进行机器人操作的可组合 3D 值图

语言是一种压缩媒介&#xff0c;人们通过它来提炼和传达他们对世界的知识和经验。大型语言模型&#xff08;LLMs&#xff09;已成为一种有前景的方法&#xff0c;通过将世界投影到语言空间中来捕捉这种抽象。虽然这些模型被认为在文本形式中内化了可概括的知识&#xff0c;但如…

智能优化算法应用:基于斑点鬣狗算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于斑点鬣狗算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于斑点鬣狗算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.斑点鬣狗算法4.实验参数设定5.算法结果6.…

【Docker】vxlan的原理与实验

VXLAN&#xff08;Virtual eXtensible Local Area Network&#xff0c;虚拟可扩展局域网&#xff09;&#xff0c;是一种虚拟化隧道通信技术。它是一种Overlay&#xff08;覆盖网络&#xff09;技术&#xff0c;通过三层的网络来搭建虚拟的二层网络。 VXLAN介绍 VXLAN是在底层…

STL(七)(map篇)

### 这里重点学习map ### 在实际做题过程中,multimap几乎用不到### unordered_map拥有极好的平均时间复杂度和极差的最坏时间复杂度,所以他的时间复杂度是不稳定的,unordered_map一般用不到,要做一个了解 1.map map是一种关联容器,用于存储一组键值对(key-value pairs),其中每…