Link to home
Start Free TrialLog in
Avatar of samliam
samliam

asked on

array arguments

Is there an easier way than the following?

int i=func(arg1, arg2, index[0], index[1], index[2], index[3],...,index[99]);
Avatar of Jim Cakalic
Jim Cakalic
Flag of United States of America image

You could pass the array itself:

    int i = func(arg1, arg2, index);

Then the method could handle all the array access. You don't even have to pass the number or items in the array (unless you want the method to process only part of it) because all array objects know and can report their length as a public int length.

Or perhaps I misunderstand the question?

Best regards,
Jim Cakalic
Avatar of hquoc
hquoc

Hi samliam,
u should not use an array directly. In java, i think that u should use a vector object such below:
Vector arg1, arg2;
int func(arg1,arg2);
And then in the definition 'func', u will use an         Enumeration object to make the iterator variable:
Enumeration index = arg1.elements();
while (index.hasMoreElements()) {
       index.nextElement();
       //your code here
}

Hope it will help u,
regards,
huuquoc
It's not necessary to use vector.
You can use array.

let say, the index datatype is int.
int index[] = new int[100];

the func():

public int func(String arg1, String arg2, int[] inx)
{
     for (int i = 0; i < inx.length; i++)
     {
          // deal with inx[i].
     }

     return 0;
}

To call func(),
int i = func(arg1, arg2, index);
like what jim_cakalic gave.
Avatar of samliam

ASKER

I tried "func(arg1, arg2, index)" in the beginning and the compiler could not "resolve the symbol func".

If I replace the 'index' with, e.g., '2,2,2', it works fine.

The function signatures are:
public native int func(String, String, int);
public native int func(String, String, int, int);
  ..., etc.
Avatar of samliam

ASKER

Error message is: "cannot resolve symbol func(String, String, int[])"
I defined the (variable-length) array with given input..
ASKER CERTIFIED SOLUTION
Avatar of Jim Cakalic
Jim Cakalic
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of samliam

ASKER

so why can you call with just 'index' instead of all elements one by one? and why is it different with JNI?
At compile time, the Java compiler determines which overloaded method it will call by matching the signature of the method call with those defined by the target class or one of its superclasses. A method signature is the combination of its name, arguments types and argument order (but does not include return type). So as described by you previously, you have a number of overridden methods declared:

    public native int func(String, String, int);
    public native int func(String, String, int, int);
    public native int func(String, String, int, int, int);
    ...
    public native int func(String, String, int, ... , int);

so that you can call the func method with two Strings and varying numbers of ints depending, I guess, on the size of the Java array which your application is holding. Correct me where I am wrong because I'm working on the assumption that what you really wanted all along was a single function that you could call with an array of ints.

For each of the above method declarations, there is a corresponding JNI method with a "matching" signature:

    JNIEXPORT jint JNICALL Java_func(JNIEnv *, jobject, jstring, jstring, jint);
    JNIEXPORT jint JNICALL Java_func(JNIEnv *, jobject, jstring, jstring, jint, jint);
    JNIEXPORT jint JNICALL Java_func(JNIEnv *, jobject, jstring, jstring, jint, jint, jint);
    ...
    JNIEXPORT jint JNICALL Java_func(JNIEnv *, jobject, jstring, jstring, jint, ... , jint);

Given this set of method signatures and the assumption that your application has an int[] holds ints that serve as arg values to the methods, you have to code a switch that "selects" the correct method to call based on the number of elements in the array. The Java compiler will ensure that methods with the specified signature actually exists while compiling the class. This really isn't any different for native methods than it is for Java methods.

The hard part is declaring a native method that takes a Java array and then using the array in the method. There is a special JNI arg type for each primitive array type and one for Object type. So, as I indicated previously, if you are writing the C++ code that implements the native methods referred to in your Java class, you can add the following to your Java class:

    public native int func(String, String, int[]);

and to your C++ implementation:

    JNIEXPORT jint JNICALL Java_func(JNIEnv *, jobject, jstring, jstring, jintArray) {
        // your C++ method
    }

Now, when you code:

    String str1 = "abc";
    String str2 = "xyz";
    int[] index = new int[50];
    int x = func(str1, str2, index);

there will actually be a func method that takes two Strings and an int[] so the compiler will not complain "cannot resolve symbol func(String, String, int[])" because there will in fact be a func method with the correct signature.

The Java Tutorial trail on JNI provides additional material and examples of using Java arrays in native methods.
    http://web2.java.sun.com/docs/books/tutorial/native1.1/implementing/array.html

Jim
Avatar of samliam

ASKER

Sorry, I didn't make it clear.

I understand what you are saying. I was just asking a basic question: (not JNI-specific)

why can I use
func("a","b",index)
to replace
func("a","b",index[0],index[1],index[3],....);

in other words, why can I just use the name of the array? In c++, the name of an array is a pointer to the starting point of the array, and functions are called by reference, so I can pass a pointer as an argument.

What's the case with Java?
A Java array is an object. As such, all use of the array is by reference -- not exactly the same thing as a pointer but reasonably analogous. When you call a method that takes an object argument, a temporary variable is created to hold a copy of the reference to the target object and that temporary variable is provided as the argument value to the method. Any change to the underlying object through the reference is visible after the method completes. But changes made to the variable holding the reference are _not_ visible.

So, you can pass an array to a method just like you can pass a String object to a method. You can operate on the array within the method using identical syntax to operations performed outside the method. Changes made to array elements will be visible after the method completes. But if you attempt to allocate a new array and assign it to the method parameter variable, that change will only be effective within the method until the method completes, then it will be lost.

In summary, it is similar to C++ but not identical. A Java array is an object -- not some blob of memory which can be addressed as you please. But because it is an object, you can pass a reference to the array to a method for it to operate upon.

Jim