我试图用
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之间的转换?
最佳答案 为此,您需要使用自己的一个替换默认的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;
}
%}
通过在默认返回的String上的幕后调用getBytes()来完全符合您的要求.
您也可以使用自己的一些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将typemap复制到其他不完全匹配的情况.