I am attempting to wrap the following C++ function with Java:
char* MyClass::to_cstring();
This output of this function is returned as a Ja
To do this you'll need to replace the default SWIG supplied typemaps with one of your own. The simplest way to do this requires just writing some Java "glue":
%module test
%typemap(jstype) char *to_cstring() "byte[]";
%typemap(javaout) char *to_cstring() {
return $jnicall.getBytes();
}
%inline %{
char *to_cstring() {
static char ret[] = "hello world";
return ret;
}
%}
Does exactly what you want by calling getBytes()
behind the scenes on the default returned String
.
You can also do this with some JNI of your own to return it as a byte array all the way through from your native code:
%module test
%typemap(jstype) char *to_cstring() "byte[]";
%typemap(jtype) char *to_cstring() "byte[]";
%typemap(javaout) char *to_cstring() {
return $jnicall;
}
%typemap(jni) char *to_cstring() "jbyteArray";
%typemap(out) char *to_cstring() {
const size_t len = strlen($1);
$result = JCALL1(NewByteArray, jenv, len);
// TODO: check that this succeeded
JCALL4(SetByteArrayRegion, jenv, $result, 0, len, (const jbyte*)$1);
}
%inline %{
char *to_cstring() {
static char ret[] = "hello world";
return ret;
}
%}
The difference here being that the mapping to byte[]
happens in the generated JNI, not in the Java glue. The glue now just proxies directly to the JNI unchanged.
I was able to test and verify these typemaps with the following Java:
public class run {
public static void main(String[] argv) {
System.loadLibrary("test");
byte[] ret = test.to_cstring();
System.out.println(ret.length);
System.out.println((char)ret[0]);
}
}
In both these examples the typemaps match on both the return type (char *
) and the function to_cstring()
. You can adjust this typemap matching to be more or less selective. It currently doesn't change most normal usage, you can also use %apply
to copy the typemap to other cases which don't exactly match.