jni c调用java_JNI--c/c++调用Java方法

本文详细介绍了如何在C/C++中调用Java的实例方法、静态方法以及构造函数,包括获取jclass和jmethodID,callXXXMethod的使用,以及静态方法的调用示例。重点展示了通过JNI进行跨语言交互的实用场景和步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上次说到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

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文件,如下图

272f043fd1af

在命令行使用javap命令

272f043fd1af

方法对应的descriptor就是方法签名,其实括号内就是参数签名,括号右边是返回值参数签名

编译c++后,再执行我们的Java程序

public static void main(String[] args) {

JniDemo2 jniDemo2 = new JniDemo2();

jniDemo2.callRandom();

}

272f043fd1af

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();

}

}

我们的桌面生成了文件

272f043fd1af

内容是:

272f043fd1af

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,所有构造方法名都是

jmethodID jmid = env->GetMethodID(hello_class, "", "()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;

}

所有构造方法名都是,还调用了HelloC的giveC方法,编译后执行Java代码

public static void main(String[] args) {

JniDemo2 jniDemo2 = new JniDemo2();

jniDemo2.callRandom();

HelloC helloC = jniDemo2.createHelloC();

}

272f043fd1af

成功的实例化了一个HelloC对象

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值