Using SWIG to convert C++ char* as char[] in Java instead of String

后端 未结 1 1730
后悔当初
后悔当初 2021-01-13 02:13

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

相关标签:
1条回答
  • 2021-01-13 02:24

    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.

    0 讨论(0)
提交回复
热议问题