Как я могу установить значение переменной типа Double для моего класса с помощью JNI?
Если я просто хочу установить значение переменной типа Double, я могу написать код:
public static native int getDoubleVar(Double dobj);
JNIEXPORT jint JNICALL
test_jni_Native_testGet(JNIEnv *env, jclass type, jobject dobj)
{
jclass DoubleClass = env->FindClass("java/lang/Double");
jfieldID valueID = env->GetFieldID(DoubleClass, "value", "D");
env->SetDoubleField(dobj, valueID, 2.3);
return 0;
}
Эти коды токэ эффект.
Но, когда я попытался установить значение переменной "Double" класса с помощью JNI, я не могу получить то, что хочу, и, конечно, оно сломалось, что немного запутало меня.
Java-коды:
public class TestDouble
{
public Double value;
public long num;
public TestDouble(long num, Double value)
{
this.num = num;
this.value = value;
}
}
Родные:
public static native int testGet(TestDouble tdobj);
c коды:
JNIEXPORT jint JNICALL
test_jni_Native_testGet(JNIEnv *env, jclass type, jobject tdobj)
{
jclass tdobjClass = env->FindClass("xxxx/TestDouble");
jfieldID valueID = env->GetFieldID(tdobjClass, "value", "D");
env->SetDoubleField(tdobj, jValueID, 2.3);
return 0;
}
Я хотел бы установить значение "value" класса "TestDouble", а тип "value" - "Double" (не double).
E/dalvikvm: VM aborting
Fatal signal 6
Send stop signal to pid:5830 in void debuggerd_signal_handler(int, siginfo_t*, void*)
Я просто вставляю здесь неправильные ключевые слова, и очевидно, что ошибка происходит в:
env->SetDoubleField(tdobj, jValueID, 2.3);
Что я могу сделать для решения этой проблемы? Большое спасибо!
2 ответа
Я получаю правильный ответ:
http://stackru.com/questions/34848605/how-to-set-the-value-of-a-double-integer-type-of-a-java-class-by-jni
JNIEXPORT jint JNICALL test_jni_Native_testSet(JNIEnv *env, jclass type, jobject tdobj)
{
//Create Integer class, get constructor and create Integer object
jclass intClass = env->FindClass(env, "java/lang/Integer");
jmethodID initInt = env->GetMethodID(env, intClass, "<init>", "(I)V");
if (NULL == initInt) return -1;
jobject newIntObj = env->NewObject(env, intClass, initInt, 123);
//Now set your integer into value atttribute. For this, I would
//recommend you to have a java setter and call it in the same way
//as shown above
//clean reference
env->DeleteLocalRef(env, newIntObj);
return 0;
}
Integer / Double и другие типы оболочки могут быть обработаны таким же образом.
Ваш код C предполагает, что TestDouble.value
это примитив double
а не объект Double
и поэтому терпит неудачу во время выполнения.
Вы можете изменить определение класса на
public class TestDouble
{
public double value;
public long num;
public TestDouble(long num, double value)
{
this.num = num;
this.value = value;
}
}
Если ваш объект Double уже был создан в коде JAVA, вам не нужно создавать новый объект Double в части C++ (извините, не C). Вы можете сделать следующее:
void setDoubleObjectField(JNIEnv* env, jobject PropertyDoubleObj, char* FieldName, double dValue)
{
jclass PropertyClass = (env)->GetObjectClass(PropertyDoubleObj);
//printf("%s\n",getClassName( env, PropertyDoubleObj));
jfieldID fidNumber = (env)->GetFieldID(PropertyClass, FieldName, "Ljava/lang/Double;");
if (fidNumber == 0)
{
CreateException(env, std::string("Failed to query field from PropertyDouble class: ") + FieldName);
return;
}
jobject DoubleObject = env->GetObjectField(PropertyDoubleObj, fidNumber);
if (DoubleObject == 0) // That means, the object was simply not created. Just create one.
{
jclass DoubleClass = env->FindClass("java/lang/Double");
jmethodID initDouble = env->GetMethodID( DoubleClass, "<init>", "(D)V");
if (NULL == initDouble)
{
CreateException(env, "Failed to create Double object.");
return;
}
DoubleObject = env->NewObject( DoubleClass, initDouble, dValue);
env->SetObjectField(PropertyDoubleObj, fidNumber, DoubleObject);
env->DeleteLocalRef(DoubleObject);
}
else
{
jclass DoubleCls = (env)->GetObjectClass(DoubleObject);
jfieldID fidNumber_double = (env)->GetFieldID(DoubleCls, "value", "D");
if (fidNumber_double == 0)
{
CreateException(env, "Failed to query value field from Double class.");
return;
}
env->SetDoubleField(DoubleObject, fidNumber_double, dValue);
}
}