tags:

views:

875

answers:

2

I have a large C structure (about 40 members, int and char[]) which I have to pass through JNI to the Java side for further processing. This happens repeatedly. (I already put the GetMethodID() etc. into an init() function on the C side so I only have to call them once.)

What would be an efficient way to do this?

I can think of:

  1. Instantiating a Java class with the appropriate members through GetMethodID( ..., "<init>", ... ) and passing all members of the C structure through the constructor;
  2. Assigning a Java struct with the appropriate members, and initializing the (public) members through SetXYZField();
  3. ...

Did I overlook something? (This is my first "close combat" with JNI.) Is there really no efficient way to "sync" a C structure and a Java structure?

What is the more efficient passing method, 1. or 2.? In case of 1., should I pass constructor parameters through CallXYZMethod() (parameter list) or CallXYZMethodA() (argument array)?

Thanks for your input.

Edit: Reworded slightly; 2. doesn't need to be a class of course, and I don't strictly need a struct on the Java side if there is some other solution to handle the C data on the Java side.

Edit 2: I do this in C++, but the struct itself stems from a C-linkage callback function, i.e. nothing C++-specific to the problem. Rephrased to read "C" instead of "C++".

+1  A: 

I'm sorry I don't have time to write an indepth answer or look in to this further but a while ago I had to do quite a lot of work with JNI and I found that using SWiG help hugely. I'm not sure of its efficiency but I imagine it generates pretty efficient code.

Anyway, check it out SWiG there's a bit on Passing structures by value and main Structures.

Good luck.

PintSizedCat
I'd rather not take on another technology / third party source, especially since I would have to read up on SWIG first. But I put this on my reading list, thank you!
DevSolar
+1  A: 

For pure efficiency, it's best to minimize calls that go through JNI, so your best bet is sending all the data in either through option 1 and creating a new object.

You could also have a "recieveUpdate( ... 40 params ...)" method on the Java side if you wanted to avoid allocating a new object per update, though it's cringeworthy design.

MHarris
Thanks for the hint regarding the number of JNI calls. I should have thought of that myself. Since this is an asynchronous callback thing, I need a new object on the Java side per call, or I get into deep multithreading trouble. ;-)
DevSolar
Oooh, good luck. Hopefully you already know this, but the JNI docs are appalling so: Make sure method IDs etc are used only in the thread that cached them, and if using native threads, call AttachCurrentThread.
MHarris
Ye flippin' gods! Thanks! Of course I assumed that caching JNIEnv, jclass and jmethodID statically once and using the cached values in the callback functions would be OK. So you mean that, every time one of my registered-as-callback C functions gets called, I have to retrieve JNIEnv etc. anew? Pffff...
DevSolar