Solved

passing an array of double in JNI

Posted on 1998-05-12
3
4,208 Views
Last Modified: 2013-11-23
Hi,
I have this method of class 'class1'

public static void method1(double[] a).

How can I pass an 'double v[6]' in C, by means of JNI?
Please show me a sample code.
Thanks.
0
Comment
Question by:jjescri
  • 2
3 Comments
 
LVL 4

Expert Comment

by:evijay
Comment Utility
Java objects are addressed and stored as pointers:

                   struct _jobject;



                   typedef struct _jobject *jobject;

                   typedef jobject jclass;

                   typedef jobject jthrowable;

                   typedef jobject jstring;

                   typedef jobject jarray;

                   typedef jarray jbooleanArray;

                   typedef jarray jbyteArray;

                   typedef jarray jcharArray;

                   typedef jarray jshortArray;

                   typedef jarray jintArray;

                   typedef jarray jlongArray;

                   typedef jarray jfloatArray;

                   typedef jarray jdoubleArray;

                   typedef jarray jobjectArray;


                   You may be wondering what the difference is between jobject and jclass. A class pointer (jclass) is a
                   description or template for a class. It is used to construct a new object (jobject) of that class.

                   The second argument of a native method is of type jobject. This is a pointer to the Java object under which this
                   method is acting. For you C++ programmers, jobject is equivalent to the this pointer. If the native method
                   had been a static function, the second argument would have been of type jclass.

                   All native methods have as their first argument the Java Native Method Interface pointer, which is described in the
                   next section.




                   Java Arrays

                   The first major point to remember when dealing with Java arrays is that arrays are themselves Java objects. Arrays
                   do have their own identifier (jobjectArray), but that is only to aid in readability. A jobjectArray reference
                   can be passed and used by any routine expecting a jobject reference.

                   All Java arrays have a length parameter. The JNI provides the function GetArrayLength() to access any array's
                   size:

                   jsize GetArrayLength(JNIEnv *env, jarray array);


                   To address the individual members of array objects, the JNI contains two major groups of functions. The group you
                   use depends on the type of data held by the array. The first group allows access to arrays of Java objects or
                   references. The second group allows access to arrays of scalar quantities.

                   In the case of arrays of objects, each array index can be set or retrieved by an interface function:

                   jobject GetObjectArrayElement(JNIEnv *env, jarray array, jsize index);

                   void SetObjectArrayElement(JNIEnv *env, jarray array, jsize index, jobject value);


                   Accessing each index with a function is very inefficient when dealing with a scalar quantity such as integers.
                   Performing matrix calculations is horribly slow. To solve this problem, the JNI provides a set of functions that allow
                   a scalar array to be accessed in the native address space.

                   Each scalar type has functions for manipulating arrays of that type. The following statement gives the calling format:

                   NativeType GetArrayElements(JNIEnv *env, jarray array, jboolean *isCopy);


                   There is no actual function called GetArrayElements(). Instead, there are variants for each scalar type. Table
                   32.3 lists all the flavors of GetArrayElements().

                   The third argument (isCopy), is a boolean set by the VM depending on whether the array was originally stored as a
                   C array. If the data of the Java array is stored contiguously, a pointer to that data is returned and isCopy is set to
                   false. If, however, the internal storage is not contiguous, the VM makes a copy of the actual data and sets
                   isCopy to true. The significance of this flag is that if the flag is false, you know you are manipulating the actual
                   array data. Any changes you make are permanent changes. If, on the other hand, you are working with a copy, your
                   changes can be released without saving.

                   Table 32.3. GetArrayElements() function types.

                   Function
                                             Native Return Type
                                                              Java Array Type
                   GetBooleanArrayElements()
                                             jboolean *
                                                              boolean[]
                   GetByteArrayElements()
                                             jbyte *
                                                              byte[]
                   GetCharArrayElements()
                                             jchar *
                                                              char[]
                   GetShortArrayElements()
                                             jshort *
                                                              short[]
                   GetIntArrayElements()
                                             jint *
                                                              int[]
                   GetLongArrayElements()
                                             jlong *
                                                              long[]
                   GetFloatArrayElements()
                                             jfloat *
                                                              float[]
                   GetDoubleArrayElements()
                                             jdouble *
                                                              double[]



                   Releasing the local copy back to the Java object is accomplished with the various versions of
                   ReleaseArrayElements(). This is its calling format:

                   void ReleaseArrayElements(JNIEnv *env, jarray array, NativeType elems, jint mode);


                   Again, the actual function name is specific to each scalar type. Table 32.4 lists the types of release functions. The
                   fourth argument (mode) to ReleaseArrayElements() controls the release mode. It has three possible values: 0
                   Copy back the data and release the local storage

                   JNI_COMMIT Copy back the data but do not release the storage

                       JNI_ABORT Release the storage without copying back the data

                       Obviously, if the local data is not a copy, the mode parameter has no effect.

                   Table 32.4. ReleaseArrayElements() function types.

                   Function
                                                 Native Return Type
                                                                  Java Array
                                                                  Type
                   ReleaseBooleanArrayElements()
                                                 jboolean *
                                                                  boolean[]
                   ReleaseByteArrayElements()
                                                 jbyte *
                                                                  byte[]
                   ReleaseCharArrayElements()
                                                 jchar *
                                                                  char[]
                   ReleaseShortArrayElements()
                                                 jshort *
                                                                  short[]
                   ReleaseIntArrayElements()
                                                 jint *
                                                                  int[]
                   ReleaseLongArrayElements()
                                                 jlong *
                                                                  long[]
                   ReleaseFloatArrayElements()
                                                 jfloat *
                                                                  float[]
                   ReleaseDoubleArrayElements()
                                                 jdouble *
                                                                  double[]



                       NOTE: If you want to work with scalar array data in an unobtrusive manner, the JNI provides a
                       second set of functions that allow the scalar array members to be copied into local storage allocated
                       and managed by the native method. GetArrayRegion() and SetArrayRegion() operate on a
                       subset of an array and use a locally allocated buffer.


                   Native methods can also create a new Java array. The NewArray() functions perform the work:



                   jarray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass,

                                         jobject initialElement);

                   jarray NewScalarArray(JNIEnv *env, jsize length);


                   Enough theory. It's time to apply what you have learned. You should now have enough knowledge to implement the
                   createVals() and reverseArray() native methods from the Demonstration class. Listing 32.3 shows the
                   completed methods; the code is also located on the CD-ROM that accompanies this book. In this example, the
                   methods manipulate an integer array, so the scalar array functions are used.

                   Listing 32.3. The native methods createVals() and reverseArray().



                   /*

                    * Class:     Demonstration

                    * Method:    createVals

                    * Signature: (I)[I

                    */

                   JNIEXPORT jintArray JNICALL Java_Demonstration_createVals

                     (JNIEnv *env, jobject DemoObj, jint len)

                   {

                       jintArray RetArray;

                       int x;

                       jint *localArray;



                       RetArray = env->NewIntArray(len);

                       localArray = env->GetIntArrayElements(RetArray, NULL);

                       for ( x = 0; x < len; x++)

                           localArray[x] = len - x - 1;

                       env->ReleaseIntArrayElements(RetArray, localArray, 0);

                       return RetArray;

                   }





                   /*

                    * Class:     Demonstration

                    * Method:    reverseArray

                    * Signature: ([I)V

                    */

                   JNIEXPORT void JNICALL Java_Demonstration_reverseArray

                     (JNIEnv *env, jobject DemoObj, jintArray vals)

                   {

                           jint x, temp;

                           jsize len;

                           jboolean isCopy;

                           jint *localArray;



                           len = env->GetArrayLength(vals);

                           localArray = env->GetIntArrayElements(vals, &isCopy);

                           for (x = 0; x < len/2; x++)

                           {

                               temp = localArray[x];

                               localArray[x] = localArray[len - x - 1];

                               localArray[len - x - 1] = temp;

                           }

                           env->ReleaseIntArrayElements(vals, localArray, 0);


                   }

                   createVals() uses NewArray() to allocate the integer array. Because NewArray() creates a proper Java
                   object, local access to the data must be acquired using GetIntArrayElements(). After the array has been
                   initialized, the local elements are released back to the Java VM.

                   Reversing the array is similar to creating it. First, the array's length is determined. After the length is known, the
                   array's contents can be acquired and manipulated as a standard C array. Notice that the isCopy parameter is not
                   required. createVals() passes null instead of a pointer because it doesn't care whether the data is a copy.
                   reverseArray() passes a valid pointer, although it never uses the information. Either technique is valid.




for more info go to
http://www.developer.com/reference/library/1575212986/htm/ch32.htm
0
 

Author Comment

by:jjescri
Comment Utility
Adjusted points to 100
0
 
LVL 4

Accepted Solution

by:
evijay earned 100 total points
Comment Utility
Here is a sample application to do that

TestDouble.java
---------------------

import java.util.*;

public class TestDouble
{
        public native static void printDoubleArray(double[] arr);
        static {
                System.loadLibrary("TestDouble");
        }
        public static void main(String args[])
        {
                double[] a = { 20.0, 30.0, 22.0 };
                printDoubleArray(a);

        }
}


TestDouble.c
------------------

#include "TestDouble.h"

JNIEXPORT void JNICALL Java_TestDouble_printDoubleArray
  (JNIEnv *env, jclass myclass, jdoubleArray myarray)
{
        jsize length;
        jboolean isCopy;
        jdouble *localArray;
        jint i;

        length = (*env)->GetArrayLength(env, myarray);
        localArray = (*env)->GetDoubleArrayElements(env, myarray, &isCopy);
        for (i = 0; i < length; i++)
                printf("%lf\n", localArray[i]);

        (*env)->ReleaseDoubleArrayElements(env, myarray, localArray, 0);

}

Step1:
javac TestDouble.java
Step 2:
javah TestDouble
Step3:
cl -Ic:\jdk1.1.4\include -Ic:\jdk1.1.4\include\win32  -LD TestDouble.c -FeTestDouble.dll c:\jdk1
.1.4\lib\javai.lib

(note: change jdk1.1.4 to appropriate directory)




0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
hash value 2 38
json example 39 108
firstChar challenge 13 82
groovy example issue 10 64
Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now