BenK BenK - 3 months ago 27
C++ Question

SWIG/Java get buffer of unknown size from C++

I have a C++ function

foo(unsigned char*& ptr)

that creates a buffer and fills it with binary data and sets ptr to point to it.
I need to get the buffer's contents from Java.

To clarify, the C++ code can be used like this:

unsigned char* ptr;
foo(ptr);
//now ptr points to a buffer, do what you want, eg
x=ptr[1];


Using
arrays_java.i
will not work because SWIG needs to know the array size in advance. I also tried the built-in typemap NIOBUFFER for
unsigned char*
modified for
unsigned char*&
but that presented problems with the generated C++ wrapper code, where the JVM crashed when attempting to use it. I also don't think using
carrays.i
as in this answer will work either because the parameter is
unsigned char*&
, not just
unsigned char*
, but I haven't tried this yet. (EDIT using
%array_functions (int * Iarr)
for a test function

void test(int*& ia)
{
ia[0]=1;
...
}


results in a JVM crash with EXCEPTION_ACCESS_VIOLATION as happened with the NIOBUFFER typemap)

Is there a way to get the buffer's size from the C++/JNI wrapper code and then create a Java array of known size from within the JNI code so I can leverage
arrays_java.i
?

Is there a way to use NIOBUFFER, possibly with modifications to its typemap and/or the generated C++ wrapper?

Is there a way to treat some
type*&
as a
type*
so I can use
carrays.i
?

Because both the NIOBUFFER typemap and
array_functions
crashed the JVM, I have a feeling that the root of my problem is the
type*&
parameter and that a way to solve this will allow either of those two options. How do I do this?

Answer

I've come up with a solution. Assuming the same function foo in my question:

  1. Write a function, say bar, that creates a local pointer, passes it into foo, and returns it. In this case, bar would be

    unsigned char* bar() { unsigned char* ptr; foo(ptr); return ptr; }

  2. In SWIG: Use %array_classes , ie, array_class(unsigned char, ShortArray)

  3. Create an instance of the array class via the pointer returned from bar by using frompointer. ShortArray sa = ShortArray.frompointer(example.bar())

This bypasses the headache of getting SWIG to work with type*& as an argin/out, since you are now dealing with ordinary pointers and arrays which SWIG handles just fine "out of the box". It also allows the Java side to receive a buffer of arbitrary size and also provides more Java-like syntax.