JNI开发

news2024/11/18 11:48:33

文件结构(选中的为生成的)
在这里插入图片描述
CMake构建不需要执行命令,会自动生成so文件打包进apk
Android mk构建需要执行命令生成so文件,再打包进apk。命令如下。


# 在jni目录下执行
# 生成com_demo_cppproject_OtherNdkTest.h头文件
javac -h ./ ../java/com/demo/cppproject/OtherNdkTest.java
# 构建出so文件
ndk-build NDK_PROJECTPATH=. NDK_APPLICATION_MK=Application.mk NDK_BUILD_SCRIPT=Android.mk NDK_LIBS_OUT=..\jniLibs\

MainActivity.java

package com.demo.cppproject;
public class MainActivity extends AppCompatActivity {

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

    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        TextView tv = binding.sampleText;

        String temp = stringFromJNI() + "\n" + new MyNdkTest().getData() + "\n"
                + new OtherNdkTest().getName() + "==" + new OtherNdkTest().count();

        tv.setText(temp);
    }

    public native String stringFromJNI();
}

MyNdkTest.java

package com.demo.cppproject;

public class MyNdkTest {
    public native String getData();
}

OtherNdkTest.java

package com.demo.cppproject;

public class OtherNdkTest {
    public native String getName();

    public native  int  count();
}

CMakeLists.txt

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.22.1)

# Declares and names the project.

project("cppproject")

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        cppproject

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        cppproject

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

native-lib.cpp

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

#ifndef _Included_com_demo_cppproject_MyNdkTest
#define _Included_com_demo_cppproject_MyNdkTest
#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jstring JNICALL Java_com_demo_cppproject_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "静态注册!cmake构建!Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

// 定义的对应java中的定义native方法, 采用动态注册
//extern "C" JNIEXPORT jstring JNICALL Java_com_demo_cppproject_MyNdkTest_getData(
JNIEXPORT jstring JNICALL getData(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "动态注册!cmake构建!get data";
    return env->NewStringUTF(hello.c_str());
}

//需要动态注册的native方法所在的类
#define JNIREG_CLAS_MAIN "com/demo/cppproject/MyNdkTest"

//创建JNINativeMethod的数组,用来存放,JNINativeMethod结构变量,
// JNINativeMethod结构存放:注册的native方法,对应的签名,C++/C的对应的JNI方法
static JNINativeMethod gMethods[] = {
        {"getData", "()Ljava/lang/String;", (void*)getData}
};

static int registerNativeMethods(JNIEnv *env, const char *className,
                                 JNINativeMethod *gMethods, int numMethods) {
    jclass clazz;
    clazz = env->FindClass(className);
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

/***
* 注册native方法
*/
static int registerNatives(JNIEnv *env) {
    if (!registerNativeMethods(env, JNIREG_CLAS_MAIN, gMethods,
                               sizeof(gMethods) / sizeof(gMethods[0]))
            ) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

/**
* 如果要实现动态注册,这个方法一定要实现
* 动态注册工作在这里进行
*/
JNIEXPORT jint

JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    jint result = -1;

    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
        return -1;
    }
    assert(env != NULL);

    if (!registerNatives(env)) { //注册
        return -1;
    }
    result = JNI_VERSION_1_4;
    return result;
}

#ifdef __cplusplus
}
#endif
#endif

demo.cpp

//
// Created by Admins on 2023/5/6.
//
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <string>
/* Header for class com_demo_cppproject_MyNdkTest */

#ifndef _Included_com_demo_cppproject_OtherNdkTest
#define _Included_com_demo_cppproject_OtherNdkTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_demo_cppproject_MyNdkTest
 * Method:    getData
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_demo_cppproject_OtherNdkTest_getName
        (JNIEnv *env, jobject){
    std::string hello = "静态注册!Android mk构建!Hi from C++";
    return env->NewStringUTF(hello.c_str());
}

/*
 * Class:     com_demo_cppproject_MyNdkTest
 * Method:    count
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_demo_cppproject_OtherNdkTest_count
        (JNIEnv *env, jobject){
    return 11;
}

#ifdef __cplusplus
}
#endif
#endif

Android.mk

# Android.mk 参数

# 设置工作目录,它用于在开发tree中查找源文件。宏my-dir由Build System提供,会返回Android.mk文件所在的目录
LOCAL_PATH := $(call my-dir)

# CLEAR_VARS变量由Build System提供。指向一个指定的GNU Makefile,由它负责清理LOCAL_xxx类型文件,
# 但不是清理LOCAL_PATH
# 所有的编译控制文件由同一个GNU Make解析和执行,其变量是全局的。所以清理后才能便面相互影响,这一操作必须有
include $(CLEAR_VARS)

# LOCAL_MODULE模块必须定义,以表示Android.mk中的每一个模块,名字必须唯一且不包含空格
# Build System 会自动添加适当的前缀和后缀。例如,demo,要生成动态库,则生成libdemo.so。
# 但请注意:如果模块名字被定义为libabd,则生成libabc.so。不再添加前缀。
LOCAL_MODULE := DEMO


# 指定参与模块编译的C/C++源文件名。不必列出头文件,build System 会自动帮我们找出依赖文件。
# 缺省的C++ 源码的扩展名为.cpp。
LOCAL_SRC_FILES := demo.cpp


# BUILD_SHARED_LIBRARY是Build System提供的一个变量,指向一个GUN Makefile Script。它负责收集自从上次调用include $(CLEAR_VARS)后的所有LOCAL_xxxxinx。并决定编译什么类型
# 1. BUILD_STATIC_LIBRARY:编译为静态库
# 2. BUILD_SHARED_LIBRARY:编译为动态库
# 3. BUILD_EXECUTABLE:编译为Native C 可执行程序
# 4. BUILD_PREBUILT:该模块已经预先编译
include $(BUILD_SHARED_LIBRARY)

# 命令:
# ndk-build NDK_PROJECTPATH=. NDK_APPLICATION_MK=Application.mk NDK_BUILD_SCRIPT=Android.mk NDK_LIBS_OUT=..\jniLibs\

Application.mk

#Application.mk 参数
APP_MODULES := DEMO
# 默认生成支持的多种类型.so
APP_ABI := all

APP_STL := c++_shared
#APP_PLATFORM := android-16不配置,打包.so会出错
APP_PLATFORM := android-19

参考:
JNI中native方法的几种注册方式
[NDK]-搭建ndk-build环境
Android Studio 4.0.+NDK .so库生成打包

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

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

相关文章

[MySQL / Mariadb] 数据库学习-Linux中二进制方式安装MySQL5.7

Linux中二进制方式安装MySQL5.7 安装安装方式官网下载安装包创建用户组mysql&#xff0c;用户和目录把下载的安装包&#xff0c;放到/home/mysql/将本地文件拷贝到远程&#xff1a; scp 文件名 –用户名计算机IP或者计算机名称:远程路径 验证包解压安装包&#xff0c;移动到/us…

【前端面试题】深拷贝的终极实现

大厂面试题分享 面试题库 前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 引子 通过本文可以学习到深拷贝的三种写法的实现思路与性能差异 首先&#xff0c;我们要理…

Hystrix 简单聊聊断路器/熔断器

本文首发自「慕课网」&#xff0c;想了解更多IT干货内容&#xff0c;程序员圈内热闻&#xff0c;欢迎关注"慕课网"&#xff01; 作者&#xff1a;风间影月|慕课网讲师 什么是Hystrix Hystrix 在SpringCloud中负责服务熔断服务降级的作用。 Hystrix 存在的目的也是…

从 Elasticsearch 到 Apache Doris,10 倍性价比的新一代日志存储分析平台

作者介绍&#xff1a;肖康&#xff0c;SelectDB 技术副总裁 导语 日志数据的处理与分析是最典型的大数据分析场景之一&#xff0c;过去业内以 Elasticsearch 和 Grafana Loki 为代表的两类架构难以同时兼顾高吞吐实时写入、低成本海量存储、实时文本检索的需求。Apache Doris…

114-Linux_mysql基本操作

文章目录 一.数据库的基本操作1.数据库的登录及退出(1)连接数据库&#xff1a;(2)退出数据库 2.查看所有数据库3.显示时间4.显示数据库版本5.创建数据库6.查看创建数据库的语句7.查看当前使用的数据库8.查看当前用户9.使用某个数据库10.删除数据库 一.数据库的基本操作 1.数据…

训练计划安排(练一休一训练分化+倒金字塔训练法)

目录 练一休一训练分化每次训练的组数12-15组 &#xff08;4-5个动作&#xff09;QA 倒金字塔训练法倒金字塔热身正式组常见误区&#xff1a; 训练补剂bcaa咖啡因肌酸蛋白粉 如何降低皮质醇水平如何提升睾酮水平文献出处睡眠8h摄入适量脂肪&#xff08;0.8g每公斤体重&#xff…

【机器学习】集成学习—Boosting—GBM(Gradient Boosting Machine)解析

【机器学习】集成学习—Boosting—GBM&#xff08;Gradient Boosting Machine&#xff09;解析 文章目录 【机器学习】集成学习—Boosting—GBM&#xff08;Gradient Boosting Machine&#xff09;解析1. 介绍2. Boosting2.1 1. 强 / 弱学习器2.1.2 AdaBoost 3. GBM3.1 GBM 特例…

如何利用ChatGPT进行论文润色-ChatGPT润色文章怎么样

ChatGPT润色文章怎么样&#xff1f; ChatGPT可以润色文章&#xff0c;使用其润色功能可以为用户提供更加整洁、清晰、文采动人的文本。但需要注意以下几点&#xff1a; 需要保持文本的一致性和完整性。当使用ChatGPT进行润色时&#xff0c;需要注意保持文本的一致性和完整性。…

单调栈的学习

文章目录 单调栈的学习什么是单调栈&#xff1f;单调栈模板暴力解法单调栈解法 单调栈的简单变形1.[496. 下一个更大元素 I](https://leetcode.cn/problems/next-greater-element-i/)2.[739. 每日温度](https://leetcode.cn/problems/daily-temperatures/)3.[503. 下一个更大元…

Kali Linux 使用远程桌面连接——xrdpxfce

[笔者系统版本] [Kali]: Kali Linux 2023.1 [Kernel]: kernel 6.1.0 [Desktop]: Xfce 4.18.1 1. 前言 在 Windows 中我们会经常使用到远程桌面这样便利的工具&#xff0c;让我们随时随地都可以使用自己想要使用的电脑&#xff0c;或者同时使用多台设备&#xff0c;那么本文就将…

open3d 源码阅读image_processing.py

目录 1. open3d.geometry.Image和numpy互转 2. 对open3d.geometry.Image进行高斯过滤 3. 高斯金字塔过滤 4. sobel过滤 5. 可视化o3d.geometry.Image 1. open3d.geometry.Image和numpy互转 import numpy as np import matplotlib.pyplot as plt import matplotlib.image a…

Midjourney从入门到精通

前言 什么是AI绘画 AI 绘画&#xff0c;顾名思义就是利用人工智能进行绘画&#xff0c;是人工智能生成内容&#xff08;AIGC&#xff09;的一个应用场景。其主要原理就是收集大量已有作品数据&#xff0c;通过算法对它们进行解析&#xff0c;最后再生成新作品&#xff0c;而算…

vue框架快速入门

vue 1、第一个Vue程序1.1、什么是Vue程序1.2、为什么要使用MVVM1.3、Vue1.4、第一个vue程序 2、基础语法2.1、v-bind2.2、v-if&#xff0c; v-else2.3、v-for2.4、v-on 3、Vue表单双绑、组件3.1、什么是双向数据绑定3.2、在表单中使用双向数据绑定3.3、什么是组件 4、Axios异步…

NixOS Legacy Boot(MBR) VmwareWorkstation安装向导

NixOS & Legacy Boot(MBR) VmwareWorkstation安装向导 目录 NixOS & Legacy Boot(MBR) VmwareWorkstation安装向导1. 下载镜像2. 创建空白虚拟机3. 使用命令行安装 NixOS3.1 Legacy Boot(MBR)3.2 格式化 4. configration.nix 配置文件5. 部署NixOS6. 部分教育站镜像源集…

Maven 3.9.1下载安装配置一条龙(无压力)亲测

这里写自定义目录标题 前言一、下载 Apache Maven 3.9.11.1、请先检查自己的IDEA是否有这个条件&#xff0c;是否兼容1.2、Maven下载 二、Windows安装配置Maven2.1、解压2.2、新建 repository 本地仓库2.3、配置环境变量MAVEN_HOME 软件路径M2_HOME 本地仓库路径配置Path2.3.1新…

关于maven

一、maven是什么 一个java项目构建工具 二、maven的作用 &#xff08;1&#xff09;依赖管理 不同框架整合&#xff0c;互相依赖jar包版本不同&#xff0c;版本不一样&#xff0c;程序跑起来就会报错。用maven管理jar包。 &#xff08;2&#xff09;跨平台构建项目 linux服…

数字信号处理3:A/D、D/A转换

信号这个东西&#xff0c;我们是实际应用中用的大多都是模拟信号&#xff0c;比如说语音、地震、雷达、声纳信号&#xff0c;这些都是模拟信号&#xff0c;但是&#xff0c;计算机想要通过数学方法处理模拟信号&#xff0c;就要先将模拟信号转换成具有有限精度的数字序列&#…

L4公司进军辅助驾驶,放话无图也能跑遍中国

作者 | Amy 编辑 | 德新 高阶智能驾驶走向规模量产&#xff0c;高精地图成为关键的门槛之一。今年&#xff0c;多家车企和智驾公司都喊出「不依赖高精地图&#xff0c;快速大规模落地」的口号。 华为、小鹏、元戎以及毫末等&#xff0c;可能是最快在国内量产 无高精图智…

TCP/IP网络编程(一)

TCP/IP网络编程读书笔记 第1章 理解网络编程和套接字1.1 理解网络编程和套接字1.1.1 构建打电话套接字1.1.2 编写 Hello World 套接字程序 1.2 基于Linux的文件操作1.2.1 底层访问和文件描述符1.2.2 打开文件1.2.3 关闭文件1.2.4 将数据写入文件1.2.5 读取文件中的数据1.2.6 文…

AI仿写软件-仿写文章生成器

AI仿写软件&#xff1a;高效出色的营销利器 作为互联网时代的营销人员&#xff0c;我们不仅需要品牌意识&#xff0c;还必须深谙营销技巧。万恶的时限压力使得我们不得不在有限的时间内输出更多的文本内容&#xff0c;以便吸引更多的关注。那么&#xff0c;如何解决这个问题呢…