Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass arrays from Java to C++ using Swig?

Tags:

java

c++

swig

I have a method in C++ that takes an array of doubles as an argument. I'm calling this method from Java and need to pass an array of doubles. The C++ routine reads and modifies the values of the array and I need those updated values in Java. How do I do this?

For example, take the C++ routine:

void myMethod( double *values, int size ) {
    for ( int i=0; i < size; i++ ) {
        values[i] = 2*values[i];
    }
}

And the Java code:

double[] values = { 1.3, 1.1 };
myMethod(values,values.length);
System.out.println(values[0]); // prints 2.6

I guess a call to myMethod cannot be made like the call above... or can it? And what is necessary in Swig to make this work. If I cannot make a call like the one above, how do I get my values to the C++ code?

like image 785
Jason Avatar asked Nov 12 '10 17:11

Jason


People also ask

Can you pass an array through a method?

You can pass arrays to a method just like normal variables. When we pass an array to a method as an argument, actually the address of the array in the memory is passed (reference). Therefore, any changes to this array in the method will affect the array.

How do you pass an array to a function and return it in Java?

Use the Arrays class to both sort and display the entire array. Next, pass the array as the sole argument to a method that doubles each element of the array and then returns the array. Use a foreach loop to show all elements in the returned array on one line separated by a single space.

How arrays are passed to methods?

Arrays can be passed to other methods just like how you pass primitive data type's arguments. To pass an array as an argument to a method, you just have to pass the name of the array without square brackets. The method prototype should match to accept the argument of the array type.

How do you pass an array value in Java?

To pass an array to a function, just pass the array as function's parameter (as normal variables), and when we pass an array to a function as an argument, in actual the address of the array in the memory is passed, which is the reference.


2 Answers

Use carrays.i!

See Swig docs on carrays

%include carrays.i
%array_functions( double, double_array )

These two lines create the following code in my module:

 public static SWIGTYPE_p_double new_double_array(int nelements) {
    long cPtr = SimulatorModuleJNI.new_double_array(nelements);
    return (cPtr == 0) ? null : new SWIGTYPE_p_double(cPtr, false);
  }

  public static void delete_double_array(SWIGTYPE_p_double ary) {
    SimulatorModuleJNI.delete_double_array(SWIGTYPE_p_double.getCPtr(ary));
  }

  public static double double_array_getitem(SWIGTYPE_p_double ary, int index) {
    return SimulatorModuleJNI.double_array_getitem(SWIGTYPE_p_double.getCPtr(ary), index);
  }

  public static void double_array_setitem(SWIGTYPE_p_double ary, int index, double value) {
    SimulatorModuleJNI.double_array_setitem(SWIGTYPE_p_double.getCPtr(ary), index, value);
  }

Which allows me to use C arrays in Java... this solves my needs and is the best solution for my problem. Thanks everyone for your answers!

like image 145
Jason Avatar answered Oct 16 '22 08:10

Jason


SWIG typemaps should allow this. The SWIG 2.0 documentation shows this example in Python.

With Java, you would use JNI code inside your SWIG typemap. JNI provides methods Get/ReleaseArrayElements. I'm guessing you could get a native array in a typemap(in), then release it in a typemap(argout).

Another approach would be to copy your array into a std::vector, using the existing SWIG typemap in std_vector.i.

like image 33
Andy Thomas Avatar answered Oct 16 '22 07:10

Andy Thomas