Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!)  
Author Message
res7cxbi





PostPosted: 2005-12-16 14:14:00 Top

java-programmer, Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) How do you make java byte arrays, fill them with values, and return
them in c++? I have no clue where to start. The JNI Tutorial a at
Java's website isn't much help because it doesn't really explain how to
make new jarrays. Any tips, how-tos and example code are welcome! (And
can anybody please explain me what's jsize? Is it just another integer?)

 
Jean-Francois Briere





PostPosted: 2005-12-16 15:13:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) To create a new jbytearray of size 32:

jbytearray bArray = env->NewByteArray(32);

jsize == jint
jint is platform dependent (it's long on 32 bits Windows for instance).

You should check the specification to help you.
http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/jniTOC.html

Regards

 
res7cxbi





PostPosted: 2005-12-16 15:34:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) Thanks - this is a huge start for me

how do you fill it with values though...?

Thanks (Again)

 
 
res7cxbi





PostPosted: 2005-12-16 16:31:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) Let me clarify my last reply...

How do you fill the jbyteArray with values from a BYTE* array (which is
native)?

 
 
Chris Uppal





PostPosted: 2005-12-16 17:10:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) email***@***.com wrote:

> how do you fill it with values though...?


You should find the JNI book helpful. Downloadable from:

http://java.sun.com/docs/books/jni/index.html

See especially section 3.3, "Accessing Arrays".

-- chris


 
 
Gordon Beaton





PostPosted: 2005-12-16 17:11:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) On 16 Dec 2005 00:30:56 -0800, email***@***.com wrote:
> How do you fill the jbyteArray with values from a BYTE* array (which
> is native)?

Using one of these mechanisms:

- SetByteArrayRegion()

- use GetByteArrayElements(), modify the local copy using "normal"
assignment, then use ReleaseByteArrayElements() to propagate your
changes back to the Java array.

/gordon

--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
 
 
Roedy Green





PostPosted: 2005-12-16 17:31:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) On 15 Dec 2005 22:14:15 -0800, email***@***.com wrote, quoted or
indirectly quoted someone who said :

>How do you make java byte arrays, fill them with values, and return
>them in c++? I have no clue where to start.

to initialise arrays see http://mindprod.com/jgloss/gotchas.html#ARRAY

passing arrays back and forth to C++ is tricky. You need a text book
to explain it all. See http://mindprod.com/jgloss/jni.html
to get started.
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
 
 
res7cxbi





PostPosted: 2005-12-16 17:52:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) Thanks guys, it works except for one thing....
The VM crashes!!!

This is the most interesting problem ever encountered.
I've tested each line one by one and after that
I've found out that the lines that are commented out
is the code that is causing the VM to crash

All the other code works perfectly. But the loop that
copies the contents of the buffer retrieved
by GetSample() (a method implemented by me)
into the jbyte array completely screws up everything

More interestingly, this method works for the first 2 invocations
if compiled with the for loop then crashes!

Compile w/o the loop method works perfectly

Im just as confused as you are

That loop is crucial because it is what fills the arrays!
Or is there a workaround?

Here's the code for it... it completely stumped me... any ideas are
highly appreciated!

JNIEXPORT jbyteArray JNICALL Java_SomeClass_readNextArray
(JNIEnv *env, jobject obj)
{
BYTE *buffer = NULL;
DWORD bufferlen = 0;
GetSample(&buffer, &bufferlen);
jbyteArray bArray = env->NewByteArray( bufferlen );
jbyte *jBytes = env->GetByteArrayElements( bArray, 0);
//Problem Code!!!
//for(DWORD i = 0; i < bufferlen; i++) {
// jBytes[i] = buffer[i];
//}
env->ReleaseByteArrayElements( bArray, jBytes, 0);
return bArray;
}

 
 
res7cxbi





PostPosted: 2005-12-16 18:01:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) Actually it might be a problem with the GetSample() implementation.
Time to check it out...... keep you guys updated

 
 
Chris Uppal





PostPosted: 2005-12-16 18:18:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) email***@***.com wrote:

> The VM crashes!!!

Not quite the right way to put it. The correct expression is "My code crashes,
taking the JVM with it!!!".


> jbyteArray bArray = env->NewByteArray( bufferlen );
> jbyte *jBytes = env->GetByteArrayElements( bArray, 0);

Never omit error-checking in JNI code. NEVER.

Other than that nothing obvious leaps out at me. Possibly the error is
elsewhere in your code. Are you /certain/ that GetSample() works, and returns
the correct values in buffer and bufferlen ? Where does the "buffer" come
from, is it malloc()/new()-ed ? If so then where's the corresponding
free()/delete[] ?

-- chris


 
 
res7cxbi





PostPosted: 2005-12-16 18:19:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) If this helps, this is the error:

#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x10001640, pid=3212,
tid=3068
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_04-b05 mixed mode,
sharing)
# Problematic frame:
# C [ArrayReaderTest.dll+0x1640]
#
# An error report file with more information is saved as
hs_err_pid3212.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#

 
 
res7cxbi





PostPosted: 2005-12-16 18:22:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) Nope... GetSample() is fine

 
 
res7cxbi





PostPosted: 2005-12-16 18:33:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) The "buffer" comes from an INSSBuffer which comes from the
IWMSyncReader in the Windows Media Format SDK. I want to pass samples
to my java app

 
 
Gordon Beaton





PostPosted: 2005-12-16 18:48:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) On 16 Dec 2005 02:21:59 -0800, email***@***.com wrote:
> Nope... GetSample() is fine

When everything is fine but your code is still crashing, then your
definition of "fine" needs adjusting.

Aside from your neglect to check return values (as Chris already
pointed out) there is nothing inherently wrong with the native code
you posted.

What do buffer and bufferlen contain after calling GetSample()? Are
you sure that the length is correct for the given buffer?

What happens if you completely remove the call to GetSample(), and do
something like this instead (just to test):

BYTE buffer[] = { 1, 2, 3, 4, 5 };
DWORD bufferlen = 5;

/gordon

--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
 
 
res7cxbi





PostPosted: 2005-12-16 18:56:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) Im running out of time... i'll just set up a buffer in the native code
and have individual elements passed to the java app by native methods
and have a for loop to reconstruct the array... really, can't figure
this out...

Do you guys think there's a performance penalty for java repeatly
asking for the next individual element or is it more favorable passing
the entire array to the java app?

 
 
res7cxbi





PostPosted: 2005-12-16 19:01:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) works perfectly... hey now that's even more interesting...

the buffer contains PCM audio data as unsigned bytes (i believe)
the buffer is usually somewhere in the 50,000 elements at any one time

 
 
res7cxbi





PostPosted: 2005-12-16 19:02:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) Sorry my last post was supposed to go right after Gordon's Post...

 
 
Gordon Beaton





PostPosted: 2005-12-16 19:29:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) On 16 Dec 2005 02:55:30 -0800, email***@***.com wrote:
> Do you guys think there's a performance penalty for java repeatly
> asking for the next individual element or is it more favorable passing
> the entire array to the java app?

Crossing the JNI boundary is expensive. Return the whole array!

/gordon

--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
 
 
Gordon Beaton





PostPosted: 2005-12-16 19:31:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) On 16 Dec 2005 03:00:41 -0800, email***@***.com wrote:
> works perfectly... hey now that's even more interesting...

So I suggest you look more closely at GetSample(). Does bufferlen
agree with buffer? Is the buffer allocated dynamically? If so,
shouldn't you free it at some point?

/gordon

--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
 
 
Gordon Beaton





PostPosted: 2005-12-16 19:51:00 Top

java-programmer >> Making and Returning Java Byte Arrays in C++ via JNI (Help! Please!) On 16 Dec 2005 01:52:19 -0800, email***@***.com wrote:
> jbyte *jBytes = env->GetByteArrayElements( bArray, 0);
> //Problem Code!!!
> //for(DWORD i = 0; i < bufferlen; i++) {
> // jBytes[i] = buffer[i];
> //}
> env->ReleaseByteArrayElements( bArray, jBytes, 0);


Not that this has anything to do with your problem, but you can
replace all of the above code (two calls to Set/GetByteArrayElements
and the intervening loop) with a single call to SetByteArrayRegion.

As an added bonus, SetByteArrayRegion likely uses a more efficient
mechanism to transfer the data.

/gordon

--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e