Dominick, On Dec 27, 2010, at 11:56 PM, Dominick Samperi wrote:
> After some trial and error I figured out how to pass matrices from R to java > and back using rJava, but this method is not documented and I wonder if there > is a > better way? > stats-rosuda-devel is the rJava list you want to use. > Anyway, here is what I found works: > > (m = matrix(as.double(1:12),3,4)) > [shows m as you would expect] > > jtest <- .jnew("JTest") > (v <- .jcall(jtest, '[[D], 'myfunc', .jarray(m), evalArray=FALSE)) > [shows v = m + 10] > > Here the JTest class has a method named myfunc that accepts > a double[][] and returns a double[][]. It simply adds 10 to every > element. > The above is plain wrong (well, that's actually a guess since you didn't provide even the signature of the method) - matrices in R are vectors, so the type is double[]. In Java there is no matrix type, so it's up to the application to represent matrices and there are many ways - some more efficient than others. From your example above it seems that you are using double[][] -- so you have to allocate the extra objects one way or another (that's why it's inefficient to represent matrices that way). But from your e-mail I have the feeling that your questions is rather about calling a method that returns double[][], so for example: public static double[][] pass(); where double[][] is a rectangular array (i.e. length of all inner arrays is equal). Unfortunately .jcall is a bit inconsistent due to bug that was introduced with the new J() API. So the intended behavior is (using class Test with the method above): > J("Test")$pass() [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 5 6 7 8 [3,] 9 10 11 12 [4,] 13 14 15 16 The $ operator makes sure that the result is converted to a native R form where possible, including recursive structures like double[][]. However, the intention of .jcall() was to never perform recursive evaluation, so this is intended: > .jcall("Test","[[D","pass", evalArray=TRUE) [[1]] [1] "Java-Array-Object[D:[...@11ddcde" [[2]] [1] "Java-Array-Object[D:[...@18fb1f7" [[3]] [1] "Java-Array-Object[D:[...@ed0338" [[4]] [1] "Java-Array-Object[D:[...@6e70c7" The intended behavior (and true in older version of rJava) was for .jcall with evalArray=FALSE to return the reference: > .jcall("Test","[[D","pass", evalArray=FALSE) [1] "Java-Array-Object[[D:[...@8f4fb3" Unfortunately, the bug is that .jcall uses rJava:::newArray() to create the reference which defaults to simplify=TRUE so the current (buggy) behavior is: > .jcall("Test","[[D","pass", evalArray=FALSE) [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 5 6 7 8 [3,] 9 10 11 12 [4,] 13 14 15 16 The real issue is that: a) if the bug is fixed, .jcall() can return just the reference which is intended but b) there is currently no exposed API for rJava:::newArray so the simplification is not available in any form for references if the bug is fixed (other than using the J/$ API). That's why I was hesitant so far to fix the bug, but I really should -- which is why the behavior your discovered will change. However, then I need to add some API to be able to convert a reference in the same way that rJava:::newArray provides and expose it - I didn't think through that part, so that's why I got stuck. I hope it helps... Cheers, Simon (PS: please continue any discussion on stats-rosuda-devel) > The parameter 'evalArray' is confusing because when > evalArray=TRUE the result is NOT evaluated (a list is returned > that you then have to apply .jevalArray to do get the answer). > > There seems to be an option to have a java reference returned > instead of the actual matrix. Can the R side manipulate the > matrix (on the java side) through this reference? > > Thanks, > Dominick > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel