JNI实例-Java和C互调

目录

  • 1. 背景
  • 2. Java调C-Demo代码
    • JNI.java
    • MainActivity.java
    • Android.mk
    • Application.mk
    • com_stone_javacallc_JNI.h
    • javacallc.c
    • build.gradle
  • 3. C调Java-Demo代码
    • 3.1 查看JNI代码方法签名的方法
    • 3.2 代码结构
    • 3.3 JNI.class
    • 3.4 MainActivity.class
    • 3.5 Android.mk
    • 3.6 Application.mk
    • 3.7 CCallJava.c
    • 3.8 com_stone_ccalljava_JNI.h
    • 3.9 layout/activity_main.xml
    • 3.10 build.gradle
    • 3.11 运行结果截图

1. 背景

在这里插入图片描述

2. Java调C-Demo代码

代码结构
在这里插入图片描述

JNI.java

package com.stone.javacallc;/*** Created by stoneWang* Created on 2024/1/16* java调用C*/
public class JNI {{System.loadLibrary("javacallc");}/*** 让C代码做加法运算,把结果返回** @param x* @param y* @return*/public native int add(int x, int y);/*** 从Java传入字符串,C代码进行拼接** @param s I am from java* @return  I am from java add I am from C*/public native String sayHello(String s);/*** 让C代码给每个元素加上10** @param intArray* @return*/public native int[] increaseArrayEles(int[] intArray);
}

MainActivity.java

package com.stone.javacallc;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.util.Log;
import android.view.View;public class MainActivity extends AppCompatActivity {private JNI jni;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);jni = new JNI();}public void add(View view) {int result = jni.add(99, 1);Log.e(MainActivity.class.getSimpleName(), "result:" + result);}public void string(View view) {String result = jni.sayHello("I am from java ");Log.e(MainActivity.class.getSimpleName(), "result:" + result);}public void array(View view) {}public void checkpw(View view) {}
}

Android.mk

LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=javacallc
LOCAL_SRC_FILES :=javacallc.c
include $(BUILD_SHARED_LIBRARY)

Application.mk

App_ABI:=all

com_stone_javacallc_JNI.h

在这里插入图片描述

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_stone_javacallc_JNI */#ifndef _Included_com_stone_javacallc_JNI
#define _Included_com_stone_javacallc_JNI
#ifdef __cplusplus
extern "C" {
#endif
/** Class:     com_stone_javacallc_JNI* Method:    add* Signature: (II)I*/
JNIEXPORT jint JNICALL Java_com_stone_javacallc_JNI_add(JNIEnv *, jobject, jint, jint);/** Class:     com_stone_javacallc_JNI* Method:    sayHello* Signature: (Ljava/lang/String;)I*/
JNIEXPORT jstring JNICALL Java_com_stone_javacallc_JNI_sayHello(JNIEnv *, jobject, jstring);/** Class:     com_stone_javacallc_JNI* Method:    increaseArrayEles* Signature: ([I)[I*/
JNIEXPORT jintArray JNICALL Java_com_stone_javacallc_JNI_increaseArrayEles(JNIEnv *, jobject, jintArray);#ifdef __cplusplus
}
#endif
#endif

javacallc.c

//
// Created by wanglei on 2024/1/16.
//
# include "com_stone_javacallc_JNI.h"
# include "string.h"/*** 把一个jstring转换成一个c语言的char* 类型.*/
char* _JString2CStr(JNIEnv* env, jstring jstr) {char* rtn = NULL;jclass clsstring = (*env)->FindClass(env, "java/lang/String");jstring strencode = (*env)->NewStringUTF(env,"GB2312");jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte("GB2312");jsize alen = (*env)->GetArrayLength(env, barr);jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);if(alen > 0) {rtn = (char*)malloc(alen+1); //"\0"memcpy(rtn, ba, alen);rtn[alen]=0;}(*env)->ReleaseByteArrayElements(env, barr, ba,0);return rtn;
}/**** @param env* @param jobj* @param ji* @param jj* @return*/
jint Java_com_stone_javacallc_JNI_add(JNIEnv *env, jobject jobj, jint ji, jint jj){int result = ji + jj;return result;
};jstring Java_com_stone_javacallc_JNI_sayHello(JNIEnv *env, jobject jobj, jstring jstr){char* fromJava = _JString2CStr(env, jstr);char* fromc = "add I am from C";// 拼接函数strcatstrcat(fromJava, fromc); // 把拼接的结果放在第一参数里面// 将char转为jstringreturn (*env)->NewStringUTF(env, fromJava);
};

build.gradle

apply plugin: 'com.android.application'android {compileSdkVersion 30buildToolsVersion "30.0.2"defaultConfig {applicationId "com.stone.javacallc"minSdkVersion 26targetSdkVersion 30versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"ndk{moduleName "javacallc"abiFilters "armeabi", "armeabi-v7a", "arm64-v8a" // cpu类型}}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}externalNativeBuild {ndkBuild {path "src/main/jni/Android.mk"}}
}dependencies {implementation fileTree(dir: "libs", include: ["*.jar"])implementation 'androidx.appcompat:appcompat:1.2.0'implementation 'androidx.constraintlayout:constraintlayout:2.0.1'testImplementation 'junit:junit:4.12'androidTestImplementation 'androidx.test.ext:junit:1.1.2'androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'}

3. C调Java-Demo代码

3.1 查看JNI代码方法签名的方法

先Build工程,生成class文件,再找到对应的class文件,打开对应目录
在这里插入图片描述
执行javap -s xxx.class,可答应该class对应的Java文件的方法签名
在这里插入图片描述

3.2 代码结构

在这里插入图片描述

3.3 JNI.class

package com.stone.ccalljava;import android.util.Log;/*** Created by stoneWang* Created on 2024/1/18*/
public class JNI {{System.loadLibrary("ccalljava");}/*** 当执行这个方法的时候,让C代码调用* public int add(int x, int y)*/public native void callbackAdd();/*** 当执行这个方法的时候,让C代码调用* public void helloFromJava()*/public native void callbackHelloFromJava();/*** 当执行这个方法的时候,让C代码调用void printString(String s)*/public native void callbackPrintString();/*** 当执行这个方法的时候,让C代码静态方法 static void sayHello(String s)*/public native void callbackSayHello();public int add(int x, int y) {Log.e("TAG", "add() x=" + x + " y=" + y);return x + y;}public void helloFromJava() {Log.e("TAG", "helloFromJava()");}public void printString(String s) {Log.e("TAG","C中输入的:" + s);}public static void sayHello(String s){Log.e("TAG",  "我是java代码中的JNI."+ "java中的sayHello(String s)静态方法,我被C调用了:"+ s);}
}

3.4 MainActivity.class

package com.stone.ccalljava;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;public class MainActivity extends AppCompatActivity {private JNI jni;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);jni = new JNI();}public void  onClick (View view) {jni.callbackAdd();jni.callbackHelloFromJava();jni.callbackPrintString();jni.callbackSayHello();}
}

3.5 Android.mk

LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=ccalljava
LOCAL_SRC_FILES :=ccalljava.c
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)

3.6 Application.mk

App_ABI:=all

3.7 CCallJava.c

#include "com_stone_ccalljava_JNI.h"
#include <stdlib.h>
#include <stdio.h>#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)/*** 让C代码调用 java 中JNI类的 public int add(int x, int y)*/
JNIEXPORT void JNICALL Java_com_stone_ccalljava_JNI_callbackAdd
(JNIEnv * env, jobject jobj){//1.得到字节码//jclass      (*FindClass)(JNIEnv*, const char*);jclass jclazz = (*env)->FindClass(env,"com/stone/ccalljava/JNI");//2.得到方法jmethodID  jmethodIDs = (*env)->GetMethodID(env, jclazz, "add", "(II)I");//3.实例化该类jobject jobject = (*env)->AllocObject(env, jclazz);//4.调用方法jint value = (*env)->CallIntMethod(env, jobject, jmethodIDs, 99, 1);//成功调用了public int add(int x, int y)printf("value===%d\n",value);LOGE("value===%d\n",value);
};/*** 让C代码调用* public void helloFromJava()*/
JNIEXPORT void JNICALL Java_com_stone_ccalljava_JNI_callbackHelloFromJava(JNIEnv * env, jobject jobj){//1.得到字节码//jclass      (*FindClass)(JNIEnv*, const char*);jclass jclazz = (*env)->FindClass(env,"com/stone/ccalljava/JNI");//2.得到方法//jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);//最后一个参数是方法签名jmethodID jmethodIDs= (*env)->GetMethodID(env,jclazz,"helloFromJava","()V");//3.实例化该类// jobject     (*AllocObject)(JNIEnv*, jclass);jobject  jobject =(*env)->AllocObject(env,jclazz);//4.调用方法//void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);(*env)->CallVoidMethod(env,jobject,jmethodIDs);//成功调用了public void helloFromJava()
};/*** 让C代码调用void printString(String s)*/
JNIEXPORT void JNICALL Java_com_stone_ccalljava_JNI_callbackPrintString(JNIEnv *env , jobject jobj){//1.得到字节码//jclass      (*FindClass)(JNIEnv*, const char*);jclass jclazz = (*env)->FindClass(env,"com/stone/ccalljava/JNI");//2.得到方法//jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);//最后一个参数是方法签名jmethodID jmethodIDs= (*env)->GetMethodID(env,jclazz,"printString","(Ljava/lang/String;)V");//3.实例化该类// jobject     (*AllocObject)(JNIEnv*, jclass);jobject  jobject =(*env)->AllocObject(env,jclazz);//4.调用方法//void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);//jstring     (*NewStringUTF)(JNIEnv*, const char*);jstring jst = (*env)->NewStringUTF(env, "I am stone!!! this is CCallJava.c");(*env)->CallVoidMethod(env,jobject,jmethodIDs, jst);//成功调用了public void helloFromJava()
};/*** 让C代码调用静态方法static void sayHello(String s)*/
JNIEXPORT void JNICALL Java_com_stone_ccalljava_JNI_callbackSayHello(JNIEnv * env, jobject jobj){//1.得到字节码//jclass      (*FindClass)(JNIEnv*, const char*);jclass jclazz = (*env)->FindClass(env,"com/stone/ccalljava/JNI");//2.得到方法//jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);//最后一个参数是方法签名jmethodID jmethodIDs= (*env)->GetStaticMethodID(env,jclazz,"sayHello","(Ljava/lang/String;)V");//3.实例化该类//void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);// static的不用实例化//4.调用方法//void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);jstring jst = (*env)->NewStringUTF(env, "I am static stone!!! this is CCallJava.c");(*env)->CallStaticVoidMethod(env,jclazz,jmethodIDs, jst);//成功调用了static void sayHello(String s)
};

3.8 com_stone_ccalljava_JNI.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_stone_ccalljava_JNI */#ifndef _Included_com_stone_ccalljava_JNI
#define _Included_com_stone_ccalljava_JNI
#ifdef __cplusplus
extern "C" {
#endif
/** Class:     com_stone_ccalljava_JNI* Method:    callbackAdd* Signature: ()V*/
JNIEXPORT void JNICALL Java_com_stone_ccalljava_JNI_callbackAdd(JNIEnv *, jobject);/** Class:     com_stone_ccalljava_JNI* Method:    callbackHelloFromJava* Signature: ()V*/
JNIEXPORT void JNICALL Java_com_stone_ccalljava_JNI_callbackHelloFromJava(JNIEnv *, jobject);/** Class:     com_stone_ccalljava_JNI* Method:    callbackPrintString* Signature: ()V*/
JNIEXPORT void JNICALL Java_com_stone_ccalljava_JNI_callbackPrintString(JNIEnv *, jobject);/** Class:     com_stone_ccalljava_JNI* Method:    callbackSayHello* Signature: ()V*/
JNIEXPORT void JNICALL Java_com_stone_ccalljava_JNI_callbackSayHello(JNIEnv *, jobject);#ifdef __cplusplus
}
#endif
#endif

3.9 layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><Buttonandroid:onClick="onClick"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="C调用Java代码" /></LinearLayout>

3.10 build.gradle

在这里插入图片描述

apply plugin: 'com.android.application'android {compileSdkVersion 30buildToolsVersion "30.0.2"defaultConfig {applicationId "com.stone.ccalljava"minSdkVersion 26targetSdkVersion 30versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"ndk{moduleName "ccalljava"abiFilters "armeabi", "armeabi-v7a", "arm64-v8a" // cpu类型}ndk {ldLibs "log"}}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}externalNativeBuild {ndkBuild {path "src/main/jni/Android.mk"}}
}dependencies {implementation fileTree(dir: "libs", include: ["*.jar"])implementation 'androidx.appcompat:appcompat:1.2.0'implementation 'androidx.constraintlayout:constraintlayout:2.0.1'testImplementation 'junit:junit:4.12'androidTestImplementation 'androidx.test.ext:junit:1.1.2'androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'}

3.11 运行结果截图

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

把Mybatis Generator生成的代码加上想要的注释

1 前言 在日常开发工作中&#xff0c;我们经常用Mybatis Generator根据表结构生成对应的实体类和Mapper文件。但是Mybatis Generator默认生成的代码中&#xff0c;注释并不是我们想要的&#xff0c;所以一般在Generator配置文件中&#xff0c;会设置不自动生成注释。带来的问题…

全职技术开发外包2023年终复盘(开篇)

掐指一算&#xff0c;我在技术外包的涛涛江水中搏浪前行已有一年半的时间。这期间&#xff0c;我逐渐完成了自我身份的认同&#xff0c;并冠以名号&#xff1a;野生码农一灯&#xff0c;醉心于帮助小企业用技术解决各种问题。 这一年半的时间&#xff0c;唏嘘与庆幸交错。唏嘘…

通过代理如何调通openai的api

调通openai的api 一、前提二、通过curl调通openai的api三、通过python调通openai的api 一、前提 会魔法上网本地运行代理软件&#xff0c;知道端口号&#xff08;如1081&#xff09;。 127.0.0.1:1081二、通过curl调通openai的api 如果在国外&#xff0c;没有qiang&#xff…

(2024,VMamba,交叉扫描,线性复杂度,全局感受野,动态权重)视觉状态空间模型

VMamba: Visual State Space Model 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 3. 方法 3.1 基础概念 3.2 2D 选择性扫描 3.3 VMamba 模型 3.3.1 整体架构 3.3.2 VSS…

无偿分享一个很有用的看源码小技巧

怎么在 idea 里面查看 git 提交记录呢&#xff1f;这个界面是藏在哪里的呢&#xff0c;我的 idea 里面怎么没有呢&#xff1f; 好的&#xff0c;是我疏忽了&#xff0c;我先入为主的认为这个大家应该都知道是怎么来的。 但是确实是有一些同学是不太清楚的&#xff0c;那我这篇…

【控制篇 / 分流】(7.4) ❀ 02. 对不同运营商IP网段访问进行分流 ❀ FortiGate 防火墙

【简介】公司有两条宽带用来上网&#xff0c;一条电信&#xff0c;一条联通&#xff0c;访问常用的某些网站速度时快时慢。领导要求&#xff0c;根据上网流量的目标运营商IP归属&#xff0c;将流量送到相应的运营商出口去&#xff0c;避免跨运营商上网。那么应该怎么做&#xf…

Python中二维数据(数组、列表)索引和切片的Bug

Python中有关数据结构索引和切片引起的Bug 一维数据索引和切片一维数组一维列表 二维数据的索引和切片二维数组二维(错误)列表 一维数据索引和切片 一维数组 对于一维数据进行索引和切片操作&#xff0c;大家都比较熟悉通过下面代码进行实现 import numpy as np data np.ra…

三、基础篇 vue Class与Style绑定

操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是 attribute&#xff0c;所以我们可以用 v-bind 处理它们&#xff1a;只需要通过表达式计算出字符串结果即可。不过&#xff0c;字符串拼接麻烦且易错。因此&#xff0c;在将 v-bind 用于 class 和 style…

基于ORB算法的图像匹配

基础理论 2006年Rosten和Drummond提出一种使用决策树学习方法加速的角点检测算法&#xff0c;即FAST算法&#xff0c;该算法认为若某点像素值与其周围某邻域内一定数量的点的像素值相差较大&#xff0c;则该像素可能是角点。 其计算步骤如下&#xff1a; 1&#xff09;基于F…

MCU最小系统原理图中四个问题详解——芯片中有很多电源管脚的原因(VDD/VSS/VBAT)、LC滤波、两级滤波、NC可切换元件

前言&#xff1a;本文对MCU最小系统原理图中的四个问题进行详解&#xff1a;芯片中有很多电源管脚的原因&#xff08;VDD/VSS/VBAT&#xff09;、LC滤波、两级滤波、NC可切换元件。本文以GD32F103C8T6最小系统原理图举例 目录&#xff1a; 芯片中有很多电源管脚的原因&#x…

自然语言处理(Natural Language Processing,NLP)解密

专栏集锦&#xff0c;大佬们可以收藏以备不时之需&#xff1a; Spring Cloud 专栏&#xff1a;http://t.csdnimg.cn/WDmJ9 Python 专栏&#xff1a;http://t.csdnimg.cn/hMwPR Redis 专栏&#xff1a;http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏&#xff1a;http://t.csdni…

zabbix邮件告警

目录 一、获取邮箱的授权码&#xff08;自行解决&#xff09; 二、 配置报警媒介&#xff08;收件人&#xff09; 三、配置报警媒介类型 四、定义一个动作&#xff08;前提是主机&#xff0c;监控项&#xff0c;触发器都已配置成功&#xff09; 一、获取邮箱的授权码&#x…