Во-первых, я хочу сказать, что старые ответы не работают (например, функция GetDirectBufferAddress в нижеприведенных ответах требует один параметр сейчас) на данный момент, как здесь:
JNI - собственный метод с параметром ByteBuffer
и здесь,
как писать и читать из bytebuffer, переходя от java в jni
Было бы лучше, если кто-то поможет..
Таким образом, я не могу правильно отправить мой ByteBuffer, который некоторые элементы заполнили, на C из Java, используя JNI, и я не могу вернуть элементы ByteBuffer снова на C
Мое собственное отклонение функции:
public native int myfunc(ByteBuffer pkt);
Распределение для него
private ByteBuffer pkt = ByteBuffer.allocate(1000);
Я называю это следующим образом:
System.out.println(myfunc(pkt)); // Doesn't works, throws exception
pkt.position(0);
System.out.println(pkt.get()); // works, when I do comment line above .println
И мои коды C как показано ниже:
JNIEXPORT jint JNICALL Java_xxx_myfunc(JNIEnv *, jobject, jobject); // header
JNIEXPORT jint JNICALL Java_xxx_myfunc(JNIEnv *env, jobject obj, jobject pkt) // function
{
jbyte *buff = (jbyte *) env->GetDirectBufferAddress(pkt);
// buff[0] = 0; I've also tried in this way
return buff[0];
//return 1; if I return 1, it returns correctly
}
когда я запускаю программу java, она выдает исключение. Как я могу вернуть свои заполненные значения ByteBuffer из C?
РЕДАКТИРОВАТЬ
A fatal error has been detected by the Java Runtime Environment:
EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x719c16b8, pid=1096, tid=1900
Чтобы использовать GetDirectBufferAddress()
вы должны гарантировать, что pkt является прямым (вы можете проверить это с помощью isDirect()). ByteBuffer.allocateDirect()
способом получения такого объекта является ByteBuffer.allocateDirect()
. Прямой ByteBuffer можно также создать из C++.
Разница между прямым и косвенным ByteBuffer четко объясняется в Java- документе.
Обновление. Я вижу ваше обновление. Нет, ByteBuffer.allocate(1000)
не создает DirectByteBuffer.
Как правильно заметил @Tom Blodget, спецификация JNI явно говорит, что GetDirectBufferAddress()
может возвращать NULL. Это работает в обоих направлениях: сам вызов не должен вылетать, если pkt является непрямым ByteBuffer, но вы должны проверить результат, даже если вы уверены, что pkt является DirectByteBuffer.
GetDirectBufferAddress()
«C» проверки результата GetDirectBufferAddress()
для NULL
(согласно документации ) охватит больше случаев, чем isDirect()
.
NULL
или isDirect()
, это обязанность пользовательской функции предоставить правильный аргумент (конечно, функция должна явно задавать этот тип аргумента в doc);)
Вы не можете использовать GetDirectBufferAddress()
за исключением прямого байтового буфера. У вас нет прямого байтового буфера.