2013-07-09 44 views
4

我试图来包装与Java下面的C++函数:使用痛饮转换C++的char *为char []在Java中,而不是字符串

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之间进行转换?

+0

至少,这必须是Java中的byte []'。 Java的'char'是一个UTF-16编码单元。 –

+0

谢谢。我更新了这个问题。 – dcdo

回答

2

要做到这一点,你需要用你自己的默认SWIG提供的默认类型。要做到这一点最简单的方法只需要编写一些Java的“胶水”:

%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测试和验证这些typemaps:

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()的typemaps比赛。您可以调整此类型图匹配以选择性更强或更弱。它目前不会改变最常用的用法,您也可以使用%apply将typemap复制到其他不完全匹配的情况。