Какой самый быстрый способ собрать данные из JNI - PullRequest
2 голосов
/ 24 января 2012

Предположим, что у меня есть структура данных C, содержащая много полей данных (> 15):

struct MyData
{
   int x;
   float y;
   ...
}

В Java я могу хранить указатель на MyData как длинный и получать доступ к членамСтруктура данных C через вызовы JNI:

long mydata_p = MyDataJNI.alloc();

int x = MyDataJNI.getX( mydata_p );
float y = MyDataJNI.getY( mydata_p );
...

Однако вызовы этих функций шокирующе дороги (в 10-100 раз дороже эквивалентного вызова функции C).Это верно, даже если реализация getX, getY, ... так же проста, как:

return ((MyData*)())->x

Q1: Почему вызовы JNI так дороги?Что еще происходит, кроме вызова указателя на функцию?(Для справки я смотрю на вызовы JNI в Android.)

Q2: Как быстрее всего сделать все элементы моей структуры C доступными на уровне Java?

Ответы [ 2 ]

1 голос
/ 24 января 2012

Вы хотите переместить все данные одним вызовом JNI.Вы можете либо скопировать его в примитивный байтовый массив (а затем извлечь из него примитивы Java, используя некоторую комбинацию ByteArrayOutputStream и DataOutputStream), либо использовать прямой NIO ByteBuffer (ByteBuffer.allocateDirect), который имеет больше смысла, если вам нужно переместить данные обратнои вперед.Прямой ByteBuffer специально разработан и оптимизирован для разделения памяти между виртуальной машиной и собственным кодом.

1 голос
/ 24 января 2012

Вместо того, чтобы хранить результаты собственного вызова во внешне управляемом указателе, вы могли бы заставить его возвращать результат в объекте Java.

Самым простым было бы записать структуры C прямо в byte[], а затем на стороне Java обернуть этот массив в ByteBuffer и прочитать его с помощью getInt(), getFloat() и т. Д.

Вы также можете вернуть массив Java-объектов, созданных для отражения ваших структур, но код был бы невероятным беспорядком, чем-то похожим на конструирование всего через отражение с явным управлением памятью.

...