我正在尝试使用JNI函数创建Java类,并使用DeviceId.java构造函数方法设置该类的一些属性。我能够使用GetMethodID获取构造函数方法,但是如何创建Device.java的新实例然后设置属性(setId和setCache)。目标是将完全填充的Device.java对象实例返回给调用者。有什么想法吗?
JNI功能:
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, "<init>", "(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;
}
}
答案 0 :(得分:7)
当您调用GetMethodID
时,您为two-arg构造函数提供了签名。因此,当您致电jstring
时,您只需要传递jbytearray
和NewObject
- 例如:
return (*env)->NewObject(env, c, cnstrctr, id, cache);
除非您决定调用0-arg构造函数,否则不需要调用setId
和setCache
方法 - 这会使代码复杂化,因为您必须调用{{1对于那些并调用它们。更容易继续沿着您所在的路线前进。
答案 1 :(得分:0)
我想将自定义 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<jclass>(env->NewGlobalRef(javaLocalClass));
// info: last argument is Java method signature
jmethodID javaConstructor = env->GetMethodID(javaGlobalClass, "<init>", "(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
。
另外,看看here。
如果您遇到类似于:JNI ERROR (app bug): attempt to use stale Global 0xf2ac01ba
的错误,您的方法签名错误,您将错误的参数传递给env->NewObject()
,或者您没有使用jni对象的全局状态 - 更多{{3} }。