Выделение длинного типа С++ для JNI jlong

Я использую JNI для передачи данных между С++ и Java. Мне нужно передать "длинный" тип, и я делаю это, используя что-то вроде:

 long myLongVal = 100;
 jlong val = (jlong)myLongVal;
 CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val);

Однако в Java, когда извлекается параметр "long", он получает как очень большое отрицательное число. Что я делаю не так?

Ответ 1

Когда вы передаете jlong ​​(который является 64-разрядным) в качестве указателя (который, скорее всего, 32-разрядный), вы обязательно потеряете данные. Я не уверен, что такое соглашение, но попробуйте либо это:

CallStaticVoidMethodA(myClass, "(J)V", (jvalue*)&val); //Note address-of!

или это:

CallStaticVoidMethod(myClass, "(J)V", val); 

Это ...A методы, которые принимают jvalue-массив, методы no-postfix принимают C-эквиваленты для скалярных типов Java.

Первый фрагмент несколько небезопасен; лучше, если более подробный, альтернативный вариант:

jvalue jv;
jv.j = val;
CallStaticVoidMethodA(myClass, "(J)V", &jv);

В некоторых экзотических архитектурах процессора требования к выравниванию для переменных jlong и jvalue могут быть разными. Когда вы объявляете союз явно, компилятор позаботится об этом.

Также обратите внимание, что тип данных С++ long часто является 32-битным. jlong ​​- 64 бита, на 32-битных платформах нестандартный эквивалент C равен long long или __int64.

Ответ 2

CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val);

Это поведение undefined. Вы бросаете целое число в качестве указателя. Это не указатель. Вам нужно, по крайней мере, передать адрес. Этот код на большинстве платформ мгновенно выйдет из строя.