Passing data from Java to JNI

171 views
Skip to first unread message

jpujol95

unread,
Jul 20, 2009, 11:28:28 AM7/20/09
to android-ndk
Hello everyone,

1) I have created an array with Java:
-----------------------------
int[] tab = {7,10,14};
-----------------------------

2) I have created a native function which is supposed to return the
first element of this array:

-----------------------------------------------------------------------------------
jint
Java_com_example_twolibs_TwoLibs_sum( JNIEnv * env,

jobject this,
jint *tab)
{
return tab[0];
}
-------------------------------------------------------------------------------------
3) After compiling, I call this function in the onCreate method:

---------------------------------------------
public native int sum(int[] tab);
....
....
int z = sum(tab);
---------------------------------------------

-> Unfortunately, it doesn't return 7 but 1073796816... I know how to
work with simple parameters such as int or float but I didn't
understand how to work with arrays.

Tank you for your help!


niko20

unread,
Jul 20, 2009, 11:42:32 AM7/20/09
to android-ndk


On Jul 20, 10:28 am, jpujol95 <jpujo...@gmail.com> wrote:
> Hello everyone,
>
> 1) I have created an array with Java:
> -----------------------------
> int[] tab = {7,10,14};
> -----------------------------
>
> 2) I have created a native function which is supposed to return the
> first element of this array:
>
> -----------------------------------------------------------------------------------



Hi,

Search google for JNI and the function "GetIntArrayElements". You need
to get a pointer to the actual data and the GetXXXArrayElements and
ReleaseXXXArrayElements functions will do that for arrays that are
passed to native code.

-niko

Doug Schaefer

unread,
Jul 20, 2009, 12:10:49 PM7/20/09
to andro...@googlegroups.com
Assuming it works the same with Dalvik as it does with the Sun VM, you might be better off using an direct ByteBuffer. It creates a real byte array and you can call the hidden address() method to return a jlong pointing to it. Now I haven't looked at Dalvik to see if it does the same, but here's hoping.

Jack Palevich

unread,
Jul 20, 2009, 1:41:23 PM7/20/09
to andro...@googlegroups.com
It is a good idea to use a direct buffer whenever you want to
communicate data between Java an native code.

However, the correct way of accessing the direct buffer's address is
to call the official supported JNI entry point void*
GetDirectBufferAddress(JNIEnv* env, jobject buf).

Doug Schaefer

unread,
Jul 20, 2009, 1:49:50 PM7/20/09
to andro...@googlegroups.com
Very cool. Thanks Jack. I need to get a newer edition of the JNI book.

Jonathan PUJOL

unread,
Jul 20, 2009, 2:57:56 PM7/20/09
to andro...@googlegroups.com
Thank you everybody. My application needs to be the fastest as possible, because of image processing...

I think I will use a buffer, does anyone have a link which explains a little this method or some code for example?

2009/7/20 Doug Schaefer <cdt...@gmail.com>

Doug Schaefer

unread,
Jul 20, 2009, 3:41:44 PM7/20/09
to andro...@googlegroups.com
Don't think it's too complicated. The GetDirect* methods give you a void * pointing to the memory and a capacity (size). You access it from Java using the ByteBuffer class.

fadden

unread,
Jul 20, 2009, 4:51:59 PM7/20/09
to android-ndk
On Jul 20, 11:57 am, Jonathan PUJOL <jpujo...@gmail.com> wrote:
> Thank you everybody. My application needs to be the fastest as possible,
> because of image processing...
> I think I will use a buffer, does anyone have a link which explains a little
> this method or some code for example?

Fastest from the native side, or fastest from the Java-language side?

Assuming the native code needs to be fast and you don't need to do a
whole lot with the data on the nonnative side, a direct byte buffer is
a good choice.

Older thread with a similar question:

http://groups.google.com/group/android-ndk/browse_thread/thread/a610cfe73aa2618e/c27be634e3305304

Jonathan PUJOL

unread,
Jul 20, 2009, 5:39:38 PM7/20/09
to andro...@googlegroups.com
You're true fadden, I only record a video with Java and I apply my whole native algorithm to each pixel! 

I'm even wondering if i could record my video from native code, that would be faster I guess, but I think a thread is already opened for that question.

2009/7/20 fadden <fad...@android.com>

Jonathan PUJOL

unread,
Jul 21, 2009, 6:17:47 AM7/21/09
to andro...@googlegroups.com
As fadden advised me, I used a ByteBuffer.

----------------------------------------------------------------------------
ByteBuffer myBuffer = ByteBuffer.allocateDirect(128); 
myBuffer.put(0,(byte) 51); 
myBuffer.put(1,(byte) 49);
----------------------------------------------------------------------------

In my native code, I want to return the 'first element' of the buffer, that's to say : 51.

-------------------------------------------------------------------------------------------
jint
Java_com_example_twolibs_TwoLibs_sum( JNIEnv *  env,
                                                                 jobject  this,
         jobject buff )
{
jbyte *BUFF = (*env)->GetDirectBufferAddress(env, buff);
return BUFF[0];
}
-----------------------------------------------------------------------------------------


Well, that function returns 12595! That's because:
   * 51 = 00110001
   * 49 = 00110011 
   * 12595 = 0011000100110011

How can I get only 1 byte instead of all the content of the buffer?


2009/7/20 Jonathan PUJOL <jpuj...@gmail.com>

Jonathan PUJOL

unread,
Jul 21, 2009, 10:58:50 AM7/21/09
to andro...@googlegroups.com
I just used jint instead of jbyte. Kind of error I never see!
All is OK now.


2009/7/21 Jonathan PUJOL <jpuj...@gmail.com>
Reply all
Reply to author
Forward
0 new messages