Проблема преобразования значения даты в JNI, получение другого длинного значения в C ++ - PullRequest
0 голосов
/ 14 января 2020

Я ужасно застрял в одном базовом c преобразовании даты в jni, поскольку (длинные) значения, передаваемые из Java в JNI / C ++, совершенно разные. Мои Java объекты даты инициализируются в классе как,

Date date1=new Date(1220227200L * 1000);

// If I convert into milliseconds such as 
long timeInMillisecond=date1.getTime();
System.out.println (timeInMillisecond )
// it obviously displays 1220227200000

В моей нативной функции я получаю как

jfieldID fid = env->GetFieldID(cls, "date1", "Ljava/util/Date");

// case 1 - value 1
jlong dobject =  (jlong) env->GetObjectField(object ,fid);
cout <<dobject;     //displays 139757766370904

// case 2 - value 2
long dobject2 = (long) env->GetObjectField(object, fid);
cout <<dobject2;  // displays 140031771862616

// case 3 - value 3
long long dobject3 = (long long) env->GetObjectField(object ,fid);
cout <<dobject3; //displays  140456034100824

Интересно, что было бы лучшим способом получить правильное значение здесь от Java в C ++. Я использую C ++ 11. Кто-то, пожалуйста, помогите мне здесь.

Обновление Извините, ребята, я думаю, что я неправильно написал несколько переменных, поэтому это не было dobject2,3 в GetObjectfield (исправление что) и фактически переписать код здесь, чтобы сделать его более понятным.

//Data.java
class Data {
  public long sDate;
  public Date schedDate;
  ....
}
// Test.java    
// Native function
public native static void sendEvent(Data EventRec);
Data Rec= new DataRec();
Rec.sDate= 1400754723399L;
Rec.schedDate = new Date(1220227200L * 1000);
sendEvent(Rec);
//C++
JNIEXPORT void JNICALL Java_Test_sendEvent  (JNIEnv *env, jclass cls, jobject jobj) {
    cls = env->FindClass("Data");
    if (cls !=NULL) {
        jmethodID ctorID = env->GetMethodID(cls, "<init>","()V");
        if (ctorID != NULL) {
            jfieldID fidLong = env->GetFieldID(cls, "sDate", "J");
            long dObj = (long) env->GetLongField(jobj,fidLong);
            cout << "C++ .. Event Date (LONG): " << dObj <<endl; // This is correct  
            jfieldID fidDate = env->GetFieldID(cls, "schedDate", "Ljava/util/Date");
            // Here is the problem area, that I tried to mimic above...             
            jobject dobject= (env->GetObjectField(jobj,fidDate));
            long dobj = env->GetLongField(dobject,fidDate);
            // OR 
            // long dObj2 = (long) env->GetLongField(jobj,fidDate);
            // ..... 
            cout << "C++ .. Date (DATE)..." << dobj;
        }
    }   
}

Ответы [ 2 ]

2 голосов
/ 15 января 2020

Ваш код JNI неправильно обращается к объектам Java.

В вашей реализации Java_Test_sendEvent() параметр jclass указывает на тип класса, в котором объявлен ваш public native static void sendEvent(Data EventRec); (который вы не показывался), а параметр jobject указывает на объект Data Rec, который ваш код Java передает в sendEvent().

Кроме того, при вызове env->GetFieldID() для Date поле, вам не хватает обязательной точки с запятой в конце строки подписи типа.

Попробуйте вместо этого:

JNIEXPORT void JNICALL Java_Test_sendEvent  (JNIEnv *env, jclass cls, jobject EventRec)
{
    jclass cls_EventRec = env->GetObjectClass(EventRec);

    jfieldID fid_sDate = env->GetFieldID(cls_EventRec, "sDate", "J");
    if (!fid_sDate) {
        // error handling...
        return;
    }

    jfieldID fid_schedDate = env->GetFieldID(cls_EventRec, "schedDate", "Ljava/util/Date;");
    if (!fid_schedDate) {
        // error handling...
        return;
    }

    jlong sDate = env->GetLongField(EventRec, fid_sDate);
    cout << "C++ .. Event Date (LONG): " << sDate << endl;

    jobject schedDate = env->GetObjectField(EventRec, fid_schedDate);
    if (schedDate) {
        jclass cls_schedDate = env->GetObjectClass(schedDate);
        jmethodID mid_getTime = env->GetMethodID(cls_schedDate, "getTime", "()J"); 
        jlong timeInMillisecond = env->CallLongMethod(schedDate, mid_getTime);
        cout << "C++ .. Date (DATE)..." << timeInMillisecond << endl;
    }
}
2 голосов
/ 14 января 2020

Вы пропускаете что-то очень важное:

jfieldID fid = env->GetFieldID(cls, "date1", "Ljava/util/Date;");
jobject dobject = env->GetObjectField(dobject, fid); // Note: "Get Object Field"

Возвращает объект java.util.Date. Вам также нужно позвонить getTime:

jmethodID mid = env->GetMethodID(cls, "getTime", "()J"); 
jlong timeInMillisecond = env->CallLongMethod(dobject, mid);
...