使用JNI创建,填充和返回Java类实例
我正在尝试使用JNI函数创建Java类,并使用DeviceId.java构造函数方法设置该类的一些属性。 我能够使用GetMethodID获取构造函数方法,但是如何创建Device.java的新实例然后设置属性(setId和setCache)。 目标是将完全填充的Device.java对象实例返回给调用者。 有任何想法吗?
JNIfunction:
JNIEXPORT jobject JNICALL Java_com_test_getID(JNIEnv *env, jclass cls) { jmethodID cnstrctr; jclass c = (*env)->FindClass(env, "com/test/DeviceId"); if (c == 0) { printf("Find Class Failed.\n"); }else{ printf("Found class.\n"); } cnstrctr = (*env)->GetMethodID(env, c, "", "(Ljava/lang/String;[B)V"); if (cnstrctr == 0) { printf("Find method Failed.\n"); }else { printf("Found method.\n"); } return (*env)->NewObject(env, c, cnstrctr); }
Java类:
package com.test; public class DeviceId { private String id; private byte[] cache; public DeviceId(){} public DeviceId(String id, byte[] cache){ this.id=id; this.cache=cache; } public byte[] getCache() { return cache; } public void setCache(byte[] cache) { this.cache = cache; } public String getId() { return id; } public void setId(String id) { this.id = id; } }
当您调用GetMethodID
,您为two-arg构造函数提供了签名。 因此,您只需要在调用NewObject
时传递jstring
和jbytearray
– 例如:
return (*env)->NewObject(env, c, cnstrctr, id, cache);
你不需要调用setId
和setCache
方法,除非你决定调用0-arg构造函数 – GetMethodID
会使你的代码复杂化,因为你必须为那些调用GetMethodID
并调用它们。 更容易继续沿着您所在的路线行进。
我想将自定义 Java对象从JNI的cpp代码返回给Java。 解决方案是从cpp函数返回一个jobject
,并在本机方法声明中使用我们的自定义Java对象。
public class PyError { public String message; public boolean occurred; public PyError(boolean occurred, String message){ this.message = message; this.occurred = occurred; } }
和Java中的方法声明:
native PyError nativePythonErrorOccurred();
在cpp方面:
extern "C" JNIEXPORT jobject JNICALL Java_com_your_package_nativePythonErrorOccurred(JNIEnv *env, jobject obj) { jclass javaLocalClass = env->FindClass("com/your/package/PyError"); if (javaLocalClass == NULL) { LOGP("Find Class Failed.\n"); } else { LOGP("Found class.\n"); } jclass javaGlobalClass = reinterpret_cast(env->NewGlobalRef(javaLocalClass)); // info: last argument is Java method signature jmethodID javaConstructor = env->GetMethodID(javaGlobalClass, "", "(ZLjava/lang/String;)V"); if (javaConstructor == NULL) { LOGP("Find method Failed.\n"); } else { LOGP("Found method.\n"); } jobject pyErrorObject = env->NewObject(javaGlobalClass, javaConstructor, true, env->NewStringUTF("Sample error body")); return pyErrorObject; }
使用javap -s java.your.package.YourClass
确定方法的签名。 另外,看看这里 。
如果您遇到类似于以下JNI ERROR (app bug): attempt to use stale Global 0xf2ac01ba
: JNI ERROR (app bug): attempt to use stale Global 0xf2ac01ba
您的方法签名是错误的,您将错误的参数传递给env->NewObject()
或者您没有使用全局状态的jni对象- 更多在这里 。