JNI 中创建对象

JNI 中创建对象

在上一篇中介绍了JNI 调用Java中的super.method()。本文是JNI系列的第九篇,介绍JNI中的如何在Native代码中创建Java对象。

系列文章的大纲如下:

JNI 中创建对象

在JNI中创建对象使用如下的一组函数:

// 创建新的对象,调用类clazz的方法ID为methodID的构造方法。
jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
jobject NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
jobject NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);

其中的methodID需要是通过GetMethodID(clazz, "<init>", sig)方法获取的。
<init>是固定的写法,且构造函数返回值都是`void`。

或者使用如下方法创建新的对象:

// 创建新的对象,但不调用构造函数,不对成员进行初始化
jobject AllocObject(JNIEnv *env, jclass clazz);

AllocObject比较少的使用。

还差一样东西,这个clazz从哪里来呢?JNI提供一下FindClass函数来查找需要的类。

// 查找并返回类,类由name指定。
jclass FindClass(JNIEnv *env, const char *name);

假如要查找类java.lang.String,那么name就是java/lang/String
如果要查找的类为java.lang.Object[],那么name[Ljava/lang/Object;"

有了这两样工具就可以在JNI中创建新的对象了。 通过下面的实例来加深一下理解。

实例

我们来看一个实例。

package myjni;

public class JNIConstructor {
    static {
        System.loadLibrary("hello");
    }

    public native Integer getIntegerObject(int number);

    public static void main(String[] args) {
        JNIConstructor obj = new JNIConstructor();
        System.out.println("In Java, the number is " + obj.getIntegerObject(1234));
    }
}

如果还不清楚如果生成头文件请参考JNI简介

生成头文件myjni_JNIConstructor.h的签名为:

/*
 * Class:     myjni_JNIConstructor
 * Method:    getIntegerObject
 * Signature: (I)Ljava/lang/Integer;
 */
JNIEXPORT jobject JNICALL Java_myjni_JNIConstructor_getIntegerObject
  (JNIEnv *, jobject, jint);

实现函数Java_myjni_JNIConstructor_getIntegerObject

#include "myjni_JNIConstructor.h"

#include <iostream>

JNIEXPORT jobject JNICALL Java_myjni_JNIConstructor_getIntegerObject(JNIEnv *env, jobject obj, jint number) {
  jclass cls = env->FindClass("java/lang/Integer");
  if (cls == nullptr) {
    std::cout << "find class java.lang.Integer failed\n";
    return nullptr;
  }

  jmethodID init = env->GetMethodID(cls, "<init>", "(I)V");
  if (init == nullptr) {
    std::cout << "get constructor failed\n";
    return nullptr;
  }

  jobject integer = env->NewObject(cls, init, number);

  jmethodID midToString = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
  if (midToString == nullptr) {
    std::cout << "get toString() method failed\n";
    return integer;
  }

  jstring result = (jstring)env->CallObjectMethod(integer, midToString);
  const char *resultStr = env->GetStringUTFChars(result, nullptr);
  std::cout << "In C++, the number is " << resultStr << "\n";
  env->ReleaseStringUTFChars(result, resultStr);

  return integer;
}

编译生成动态库,并运行Java程序得到输出:

In Java, the number is 1234
In C++, the number is 1234

vx搜:极客Furzoom,关注获取第一手资料。

本文完。

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页

打赏作者

枫竹梦

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值