使用SWIG将C ++ char *转换为Java中的char []而不是String

时间:2013-07-09 12:43:30

标签: c++ swig

我试图用Java包装以下C ++函数:

char* MyClass::to_cstring();

此函数的此输出作为Java String对象返回。我希望它作为char[] Java数组返回。我目前正在使用“typemaps.i”和“std_string.i”。有没有办法覆盖行为,使得std :: string仍然作为Java String返回,但char*作为Java char数组返回?

如何使用Java byte[]而不是char[],那么不必担心在8位C ++字符和Java的16位Unicode之间进行转换?

1 个答案:

答案 0 :(得分:3)

要执行此操作,您需要使用自己的一个替换默认的SWIG提供的类型地图。最简单的方法就是编写一些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;
}
%}

通过在默认情况下在幕后调用getBytes()返回String,您确切想要的是什么。

您也可以使用自己的一些JNI将其作为字节数组从本机代码返回:

%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;
}
%}

这里的区别在于映射到byte[]发生在生成的JNI中,而不是Java胶水中。胶水现在只是直接代替JNI。

我能够使用以下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]);
  }
}

在这两个示例中,类型映射都匹配返回类型(char *)和函数to_cstring()。您可以调整此类型贴图匹配,以便或多或少具有选择性。它目前不会改变大多数正常使用情况,您也可以使用%apply将类型映射复制到其他不完全匹配的情况。