I have sample .h file like below:
class Test
{
public:
void SelectValues(long long values[])
};
I used SWIG and created JNI interfac
What you've done here with array_functions
is correct and usable, but it's focused on wrapping the C++ code directly, and it won't be using an underlying Java array. You can use it with something like:
SWIGTYPE_p_long_long array = MyLib.new_long_long_array(100); // new array with 100 elements.
for (int i = 0; i < 100; ++i) {
long_long_array_setitem(array, i, i);
}
new Test().SelectValues(array);
where array is just a proxy to a "real" C++ chunk of memory that you can read/write from on the Java side and pass to wrapped functions.
I'm guessing from your question that you're interested in making this feel more "natural" on the Java side. SWIG also provides array_class
which wraps an array similarly, but as a proper object rather than a collection of static functions. For example if you changed your interface file to use array_class(long long, LongLongArray)
instead of array_functions
you can do:
LongLongArray array = new LongLongArray(100);
for (int i = 0; i < 100; ++i) {
array.setitem(i,i);
}
new Test().SelectValues(array.cast());
You can actually make SWIG do more than that with a few typemaps if you want to. Your example class doesn't take a length in SelectValues
so I'm assuming you're 0 terminating the array although you can equally well pass the length in with a few simple changes.
(For convenience I %inline
d your class to reduce the number of files and added a dummy implementation of it for testing)
%module MyLib
%{
#include <iostream>
%}
%typemap(jtype) long long values[] "long[]"
%typemap(jstype) long long values[] "long[]"
%typemap(javain) long long values[] "$javainput"
%typemap(jni) long long values[] "jlongArray"
%typemap(in) long long values[] {
jboolean isCopy;
$1 = JCALL2(GetLongArrayElements, jenv, $input, &isCopy);
}
%inline %{
class Test
{
public:
void SelectValues(long long values[]) {
while (*values) {
std::cout << *values++ << "\n";
}
}
};
%}
Here we said that both the proxy class SWIG generates and the JNI class it generates are going to be working with long[]
, i.e. a Java array. We don't need to do anything in the Java Proxy to Java JNI conversion, so the javain
typemap is just a straight pass through. On the C++ side of the JNI that's a jlongArray
, which we also specified in another typemap.
We then need an in
typemap to arrange converting from jlongArray to long long[]
in the C++ side - there's a single JNI call for that and we don't care if it's a copy or the actual memory from the JVM that we end up using. (You might care if you wanted to modify the results and make it visible back inside Java for example)
I tested this with:
public class run {
public static void main(String[] argv) {
System.loadLibrary("mylib");
long arr[] = {100,99,1,0}; // Terminate with 0!
new Test().SelectValues(arr);
}
}
Which did exactly as you'd hope.