JNI--c/c++调用Java方法

上次说到c/c++调用Java的变量,同样的c/c++也可以调用Java的方法

1.c/c++native方法调用Java非静态方法

首先看下我们Java的类
package com.aruba.jniapplication;

import java.util.Random;

public class JniDemo2 {

    static {
        System.load("C:\\Users\\tyqhc\\source\\repos\\JniApplication\\x64\\Debug\\JniApplication.dll");
    }

    public native void callRandom();

    private int getRandom(int bound) {
        return new Random().nextInt(bound);
    }

    public static void main(String[] args) {
    }

}

我们在c/c++代码中调用Java的getRandom方法,按照之前的套路,我们直接开始写c++代码

head文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_aruba_jniapplication_JniDemo */

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

JNIEXPORT void JNICALL Java_com_aruba_jniapplication_JniDemo2_callRandom
(JNIEnv*, jobject);

#ifdef __cplusplus
}
#endif
#endif

cpp文件

#include "my_jni2.h"
#include<string>

using namespace std;

JNIEXPORT void JNICALL Java_com_aruba_jniapplication_JniDemo2_callRandom
(JNIEnv* env, jobject jobj) {
    //获取jclass
    jclass jclz = env->GetObjectClass(jobj);

    //三个参数:1:对应类的jclass 2:方法名 3:方法签名
    jmethodID jmid = env->GetMethodID(jclz,"getRandom","(I)I");
    //根据返回值,调用相应方法,我这边返回值是int,第三个参数为可变参数,就是调用方法需要传入的参数
    jint int_random = env->CallIntMethod(jobj, jmid,500);

    //打印
    printf("%d",int_random);
}
这边先获取jclass,再通过jclass获取jmethodID ,然后根据jmethodID调用Java的方法,最后打印输出。GetMethodID方法需要方法签名,下面介绍获取签名的方法,build下AS工程,找到我们需要反编译的class文件,如下图
在命令行使用javap命令
方法对应的descriptor就是方法签名,其实括号内就是参数签名,括号右边是返回值参数签名
编译c++后,再执行我们的Java程序
    public static void main(String[] args) {
        JniDemo2 jniDemo2 = new JniDemo2();
        jniDemo2.callRandom();
    }
Java方法被成功调用了,一般c/c++调用Java方法用于使用一些Java封装好的方法,而c/c++库函数又没有提供,自己手写又比较复杂,此时调用Java的方法会非常便利

2.c/c++静态native方法调用Java静态方法

我们在JniDemo2.java类中新增下面两个方法
    public static native void callUUID();

    private static String getUUID() {
        return UUID.randomUUID().toString();
    }
下面是c++代码
JNIEXPORT void JNICALL Java_com_aruba_jniapplication_JniDemo2_callUUID
(JNIEnv*, jclass);
JNIEXPORT void JNICALL Java_com_aruba_jniapplication_JniDemo2_callUUID
(JNIEnv* env, jclass jclz) {
    //获取静态方法的jmethodID
    jmethodID jmid = env->GetStaticMethodID(jclz, "getUUID", "()Ljava/lang/String;");
    //调用静态Java方法
    jstring jstr = (jstring)env->CallStaticObjectMethod(jclz, jmid);

    //将Java方法返回值转换为c++string对象
    string uuid = env->GetStringUTFChars(jstr, NULL);

    //创建一个文件
    string file_name = uuid + ".txt";
    string file_path = "C://Users//tyqhc//Desktop//" + file_name;
    FILE* f = fopen(file_path.c_str(),"w");
    fprintf(f,"hello Java %s",uuid.c_str());
    fclose(f);
}
这边调用了Java的getUUID方法,并创建一个以UUID命名的txt文件,内容是hello Java 加上UUID,编译后执行Java代码
package com.aruba.jniapplication;

import java.util.Random;
import java.util.UUID;

public class JniDemo2 {

    static {
        System.load("C:\\Users\\tyqhc\\source\\repos\\JniApplication\\x64\\Debug\\JniApplication.dll");
    }

    public native void callRandom();

    private int getRandom(int bound) {
        return new Random().nextInt(bound);
    }

    public static native void callUUID();

    private static String getUUID() {
        return UUID.randomUUID().toString();
    }

    public static void main(String[] args) {
        JniDemo2 jniDemo2 = new JniDemo2();
        jniDemo2.callRandom();

        jniDemo2.callUUID();
    }

}
我们的桌面生成了文件
内容是:

3.c/c++调用Java对象的构造方法

首先我们创建一个Java类:HelloC
public class HelloC {
    public HelloC() {
    }

    private long giveC() {
        return 1234;
    }
}
我们在JniDemo2.java中新增native方法,然后编写c++代码
/*
 * Class:     com_aruba_jniapplication_JniDemo2
 * Method:    createHelloC
 * Signature: ()Lcom/aruba/jniapplication/HelloC;
 */
JNIEXPORT jobject JNICALL Java_com_aruba_jniapplication_JniDemo2_createHelloC
  (JNIEnv *, jobject);
JNIEXPORT jobject JNICALL Java_com_aruba_jniapplication_JniDemo2_createHelloC
(JNIEnv* env, jobject jobj) {
    //首先找到我们需要实例化的class,通过包名加类名
    jclass hello_class = env->FindClass("com/aruba/jniapplication/HelloC");

    //获取构造方法jmethodID,所有构造方法名都是<init>
    jmethodID jmid = env->GetMethodID(hello_class, "<init>", "()V");
    //实例化
    jobject hello = env->NewObject(hello_class,jmid);

    //调用hello的giveC方法
    jmid = env->GetMethodID(hello_class, "giveC", "()J");
    jlong data = env->CallLongMethod(hello,jmid);
    printf("\n %ld",data);

    return hello;
}
所有构造方法名都是<init>,还调用了HelloC的giveC方法,编译后执行Java代码
    public static void main(String[] args) {
        JniDemo2 jniDemo2 = new JniDemo2();
        jniDemo2.callRandom();

       HelloC helloC = jniDemo2.createHelloC();
    }
成功的实例化了一个HelloC对象

总结:c/c++调用Java方法流程:根据jclass获取jmethodID->根据具体返回值调用相应的callXXXMethod方法或者构造方法的话调用NewObject方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容