Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #18998 > unrolled thread

JNI return jobjectArray

Started byPhilipp Kraus <philipp.kraus@flashpixx.de>
First post2012-09-30 22:23 +0200
Last post2012-10-01 23:46 +0100
Articles 9 — 6 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  JNI return jobjectArray Philipp Kraus <philipp.kraus@flashpixx.de> - 2012-09-30 22:23 +0200
    Re: JNI return jobjectArray markspace <-@.> - 2012-09-30 14:56 -0700
      Re: JNI return jobjectArray Philipp Kraus <philipp.kraus@flashpixx.de> - 2012-10-01 00:23 +0200
        Re: JNI return jobjectArray markspace <-@.> - 2012-09-30 19:21 -0700
          Re: JNI return jobjectArray Lew <lewbloch@gmail.com> - 2012-09-30 21:14 -0700
            Re: JNI return jobjectArray markspace <-@.> - 2012-10-01 08:32 -0700
        Re: JNI return jobjectArray "Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org> - 2012-10-01 09:39 +0100
    Re: JNI return jobjectArray Roedy Green <see_website@mindprod.com.invalid> - 2012-10-01 10:21 -0700
    Re: JNI return jobjectArray Steven Simpson <ss@domain.invalid> - 2012-10-01 23:46 +0100

#18998 — JNI return jobjectArray

FromPhilipp Kraus <philipp.kraus@flashpixx.de>
Date2012-09-30 22:23 +0200
SubjectJNI return jobjectArray
Message-ID<k4a9gd$usp$1@online.de>
Hello,

I hope this question is not OT.

I create a JNI call for this Java method

class myclass {

    void native mymethod( Double[] x )
}

so the parameter x should be a call-by-reference, I would set x in the 
native JNI function:

void mymethod( JNIEnv *jenv, jclass jcls, jobjectArray& jarg )
{
   // do something
   jobjectArray t = .....

   jarg = t;
}

How can I set the jobjectArray& back, so the data is return in the parameter x?
IMHO I need jenv->NewGlobalRef, os this the correct use jarg = 
(jobjectArray)jenv->NewGlobalRef( (jobject*) &t ) ?

Thanks

Phil

[toc] | [next] | [standalone]


#19000

Frommarkspace <-@.>
Date2012-09-30 14:56 -0700
Message-ID<k4af7c$tdo$1@dont-email.me>
In reply to#18998
On 9/30/2012 1:23 PM, Philipp Kraus wrote:
> Hello,
>
> I hope this question is not OT.
>
> I create a JNI call for this Java method
>
> class myclass {
>
>     void native mymethod( Double[] x )
> }
>
> so the parameter x should be a call-by-reference, I would set x in the
> native JNI function:
>
> void mymethod( JNIEnv *jenv, jclass jcls, jobjectArray& jarg )
> {
>    // do something
>    jobjectArray t = .....
>
>    jarg = t;
> }
>
> How can I set the jobjectArray& back, so the data is return in the
> parameter x?


You can't.  Java doesn't have a pass-by-reference call scheme, at all. 
Java uses only pass by value.  You could:

1. Return the new array as a return value.
2. Create a reference to a reference so you can replace the 2nd one:

 > class myclass {
 >
 >     void native mymethod( Double[][] x )
 > }

will give you a pointer to an array which you can then modify.

A Google search for "Java pass by reference" will give you lots of 
details.  Maybe add "jni" to get some clues more specific results for 
your particular situation.

<https://www.google.com/search?q=java+pass+by+reference>

[toc] | [prev] | [next] | [standalone]


#19001

FromPhilipp Kraus <philipp.kraus@flashpixx.de>
Date2012-10-01 00:23 +0200
Message-ID<k4aghk$45u$1@online.de>
In reply to#19000
On 2012-09-30 23:56:57 +0200, markspace said:

> On 9/30/2012 1:23 PM, Philipp Kraus wrote:
>> Hello,
>> 
>> I hope this question is not OT.
>> 
>> I create a JNI call for this Java method
>> 
>> class myclass {
>> 
>> void native mymethod( Double[] x )
>> }
>> 
>> so the parameter x should be a call-by-reference, I would set x in the
>> native JNI function:
>> 
>> void mymethod( JNIEnv *jenv, jclass jcls, jobjectArray& jarg )
>> {
>> // do something
>> jobjectArray t = .....
>> 
>> jarg = t;
>> }
>> 
>> How can I set the jobjectArray& back, so the data is return in the
>> parameter x?
> 
> 
> You can't.  Java doesn't have a pass-by-reference call scheme, at all. 
> Java uses only pass by value.  You could:
> 
> 1. Return the new array as a return value.
> 2. Create a reference to a reference so you can replace the 2nd one:
> 
>  > class myclass {
>  >
>  >     void native mymethod( Double[][] x )
>  > }
> 
> will give you a pointer to an array which you can then modify.
> 
> A Google search for "Java pass by reference" will give you lots of 
> details.  Maybe add "jni" to get some clues more specific results for 
> your particular situation.

You are not right, because the problem is not the Java side, it is the 
JNI (C/C++) side, so under C/C++ exists call-by-reference.

In detail I have got a native (C) methode, that shows in Java:

class myclass {
	native void mymethod( Double[] x, Double[][] y )
}

The JNI glue code generates a

void mymethod (JNIEnv* jnv, jclass jcls, jobjectArray arg1, jobjectArray arg2 )

So the reference to the underlaying heap object is passed in the JNI 
code parameters arg1 & arg2,
so I would modify this two heap adresses.

If I call in Java this code:

Double[] x = null;
Double[][] y = null;

myclass.mymethod(x, y);
// x & y are now filled with data


in x & y should be create a new array object, so I need a 
GlobalReference on the heap of the VM
and push back the reference. I can create the global object on the VM 
heap, but how can I push back
the reference

[toc] | [prev] | [next] | [standalone]


#19004

Frommarkspace <-@.>
Date2012-09-30 19:21 -0700
Message-ID<k4auo2$fvf$1@dont-email.me>
In reply to#19001
On 9/30/2012 3:23 PM, Philipp Kraus wrote:

> You are not right,


I'm not right?  And yet...


 > heap, but how can I push back
 > the reference


...the problem still exists.


> In detail I have got a native (C) methode, that shows in Java:


Truthfully, there is not enough detail here for me to guess what the 
problem really is.  You're showing method signatures but no code.


> If I call in Java this code:
>
> Double[] x = null;
> Double[][] y = null;
>
> myclass.mymethod(x, y);


No this will not work.  I guess I was not specific enough: *you* have to 
create a reference to the array reference you want to modify.  That 
doesn't happen if the parameter is null.

   Double x = { {1.2} };

Now you have something to modify.  Java does NOT have pass by reference, 
you must do it yourself.  I did a Google search, and I didn't see the 
solution, so here I guess is some lost knowledge.  This is Java, you'll 
have to translate to C++ on your own:

class Example {

   // manual "pass by reference"
   void makeNewDoubleArray( Double [][] x ) {
     x[0] = new Double[] { 1.1, 2.2, 3.3 };
   }

   public static void main( String... args ) {
     Double[] y = {0.0};
     Double[][] wrapper = { {} };
     wrapper[0] = y;           // pack
     makeNewDoubleArray( wrapper );
     y = wrapper[0]            // unpack
     System.out.println( java.util.Arrays.deepToString( y ) );
   }
}

Code is untested; watch out for silly errors.



[toc] | [prev] | [next] | [standalone]


#19005

FromLew <lewbloch@gmail.com>
Date2012-09-30 21:14 -0700
Message-ID<8ae235a8-d70a-45c8-b94f-8f7190b940f1@googlegroups.com>
In reply to#19004
markspace wrote:
> Philipp Kraus wrote:
>> You are not right,
> 
> I'm not right?  And yet...
> 
>> heap, but how can I push back the reference
> 
> ...the problem still exists.
>
>> In detail I have got a native (C) methode, that shows in Java:
> 
> Truthfully, there is not enough detail here for me to guess what the 
> problem really is.  You're showing method signatures but no code.

What he did show was a parameter passed from Java as a C++ reference.

Does that even work? Java doesn't have anything like C++ references to pass.

That being the advice the OP blew off immediately.

>> If I call in Java this code:
>>
>> Double[] x = null;

'x' is equivalent to a pointer, not a reference.

Pardon my ignorance, but what if you used a pointer in the native code
instead of a reference?

> > Double[][] y = null;
>>
>> myclass.mymethod(x, y);

Java convention calls for type names to start with an upper-case letter
and use camel case.

> No this will not work.  I guess I was not specific enough: *you* have to 
> create a reference to the array reference you want to modify.  That 

Well, in C++ terms, wouldn't that be a pointer?

> doesn't happen if the parameter is null.
> 
>    Double x = { {1.2} };
> 
> Now you have something to modify.  Java does NOT have pass by reference, 
> you must do it yourself.  I did a Google search, and I didn't see the 
> solution, so here I guess is some lost knowledge.  This is Java, you'll 
> have to translate to C++ on your own:
> 
> class Example {
> 
>    // manual "pass by reference"
> 
>    void makeNewDoubleArray( Double [][] x ) {
>      x[0] = new Double[] { 1.1, 2.2, 3.3 };
>    }
> 
>    public static void main( String... args ) {
>      Double[] y = {0.0};
>      Double[][] wrapper = { {} };
>      wrapper[0] = y;           // pack
>      makeNewDoubleArray( wrapper );
>      y = wrapper[0]            // unpack
>      System.out.println( java.util.Arrays.deepToString( y ) );
>    }
> }
> 
> Code is untested; watch out for silly errors.

I am ignorant of the ways of JNI, so my question might be extraordinarily 
off base.

-- 
Lew

[toc] | [prev] | [next] | [standalone]


#19012

Frommarkspace <-@.>
Date2012-10-01 08:32 -0700
Message-ID<k4cd2u$6qc$1@dont-email.me>
In reply to#19005
On 9/30/2012 9:14 PM, Lew wrote:

> I am ignorant of the ways of JNI, so my question might be extraordinarily
> off base.
>


I'm pretty ignorant of JNI also, but I'm making the assumption that 
Chris Upal is correct (he posted after you and I; I was just making an 
educated guess).  It *must* work the same was as native Java, since 
there's no other way for Java to handle it.

The OP is just confused about reference vs value, and hoping Java has an 
"out."  It doesn't, and he'll have to adjust his thinking.

[toc] | [prev] | [next] | [standalone]


#19008

From"Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org>
Date2012-10-01 09:39 +0100
Message-ID<K-SdnUzujNRnyvTNnZ2dnUVZ7q-dnZ2d@bt.com>
In reply to#19001
Philipp Kraus wrote:

> > You can't.  Java doesn't have a pass-by-reference call scheme, at all.
> > Java uses only pass by value.  You could:
> > [...]
> You are not right, because the problem is not the Java side, it is the
> JNI (C/C++) side, so under C/C++ exists call-by-reference.

Not relevant.  The way you do this with JNI is /exactly/ the same as you would 
do it using native Java.  Either you allocate the array before calling the 
function which will fill in the elements (but, of course, cannot change the 
size of the array), or you make the function allocate, populate, /and return/ 
the new array.  (There are other options such as passing an object which has a 
field to which the array can be assigned, but that's just pointless 
over-complication).

    -- chris 

[toc] | [prev] | [next] | [standalone]


#19016

FromRoedy Green <see_website@mindprod.com.invalid>
Date2012-10-01 10:21 -0700
Message-ID<c3kj68dkag5d80f8g2vpg6nf0ovvmcdot5@4ax.com>
In reply to#18998
On Sun, 30 Sep 2012 22:23:48 +0200, Philipp Kraus
<philipp.kraus@flashpixx.de> wrote, quoted or indirectly quoted
someone who said :
Set up your glue methods in Java and mark them native.

Then use javah to create your c stubs.  The write your C/C++ methods.

See http://mindprod.com/jgloss/jni.html
-- 
Roedy Green Canadian Mind Products http://mindprod.com
The iPhone 5 is a low end Rolex. 

[toc] | [prev] | [next] | [standalone]


#19023

FromSteven Simpson <ss@domain.invalid>
Date2012-10-01 23:46 +0100
Message-ID<14jpj9-va7.ln1@s.simpson148.btinternet.com>
In reply to#18998
On 30/09/12 21:23, Philipp Kraus wrote:
> class myclass {
>
>    void native mymethod( Double[] x )
> }

I realise this snippet could be just for illustration, but 'native' must 
come before the return type in real code.  Missing semicolon too.

> so the parameter x should be a call-by-reference, I would set x in the 
> native JNI function:
>
> void mymethod( JNIEnv *jenv, jclass jcls, jobjectArray& jarg )

When I tried the class (after the fixes) with javah, I got this:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class myclass */

#ifndef _Included_myclass
#define _Included_myclass
#ifdef __cplusplus
extern "C" {
#endif
/*
  * Class:     myclass
  * Method:    mymethod
  * Signature: ([Ljava/lang/Double;)V
  */
JNIEXPORT void JNICALL Java_myclass_mymethod
   (JNIEnv *, jobject, jobjectArray);

#ifdef __cplusplus
}
#endif
#endif

The jobjectArray parameter has no '&'.  If it had one, it would not be 
possible to link it with a C implementation.  If an '&' is inserted 
manually, and the function is implemented in C++, the machine code would 
likely be identical to an equivalent function using a pointer, but the 
JVM would not pass a jobjectArray* to it, and you'd get undefined behaviour.


-- 
ss at comp dot lancs dot ac dot uk

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web