Swig: convert return type std::string(binary) to java byte[]

后端 未结 1 1467
梦毁少年i
梦毁少年i 2021-01-13 17:54

My situation is that i have a C++ class (MyClass) with a method that has the following signature:

bool getSerialized(const stdString & name, std::string         


        
1条回答
  •  星月不相逢
    2021-01-13 18:36

    You can do what you're trying to do with a few typemaps and some JNI. I put together an example:

    %module test
    
    %include 
    
    %typemap(jtype) bool foo "byte[]"
    %typemap(jstype) bool foo "byte[]"
    %typemap(jni) bool foo "jbyteArray"
    %typemap(javaout) bool foo { return $jnicall; }
    %typemap(in, numinputs=0) std::string& out (std::string temp) "$1=&temp;"
    %typemap(argout) std::string& out {
      $result = JCALL1(NewByteArray, jenv, $1->size());
      JCALL4(SetByteArrayRegion, jenv, $result, 0, $1->size(), (const jbyte*)$1->c_str());
    }
    // Optional: return NULL if the function returned false
    %typemap(out) bool foo {
      if (!$1) {
        return NULL;
      }
    }
    
    %inline %{
    struct Bar {
      bool foo(std::string& out) {
        std::string s;
        s.push_back('H');
        s.push_back('o');
        s.push_back(0);
        s.push_back('l');
        s.push_back('a');
        out = s;
        return true;
      }
    };
    %}
    

    It states that the C++ wrapper with return a Java byte array for the functions that match bool foo. It also sets up a temporary std::string to give to the real implementation of foo that hides the input parameter from the Java interface itself.

    Once the call has been made it creates and returns a byte array provided the function didn't return false.

    I checked that it all worked as expected with:

    public class run { 
      public static void main(String[] argv) {
        String s = "ho\0la";
        System.out.println(s.getBytes().length);
    
        System.loadLibrary("test");
        Bar b = new Bar();
        byte[] bytes = b.foo();
        s = new String(bytes);
        System.out.println(s + " - " + s.length());
        assert(s.charAt(2) == 0);
      }
    }
    

    You should be aware of the implications of the cast to const jbyte* from the return type of c_str() - it may not always be what you wanted.

    As an alternative if the size of the output byte array was actually fixed or trivially predictable you could pass that in pre-allocated as the input to begin with. This would work because arrays are effectively passed by reference into functions in the first place.

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