我的情况是我有一个 C++ 类(MyClass),其方法具有以下签名:
bool getSerialized(const stdString & name, std::string & serialized);
其中 name 是一个 in 参数,而 serialized 是一个 out 参数。
我通过在“i”文件中进行 %extend 和 %ignore 声明使其工作,如下所示:
%extend MyClass{
std::string getSerialized(const std::string & name){
std::string res;
$self->getSerialized(name, res);
return res;
};
%rename("$ignore", fullname=1) "MyClass::getSerialized";
所以方法 con 可以从 Java 中使用,例如:
MyClass mc = new MyClass();
String res = mc.getSerialized("test");
但是现在我遇到了一个问题,序列化的 std::string 包含二进制数据,包括 '\0' 字符女巫表示 C 字符串的结尾,实际上以下代码显示了 C++ 中的问题:
std::string s;
s.push_back('H');
s.push_back('o');
s.push_back(0);
s.push_back('l');
s.push_back('a');
std::cout << "Length of std::string " << s.size() << std::endl;
std::cout << "CString: '" << s.c_str() << "'" << std::endl;
上面的代码显示:
Length of std::string 5
CString: 'Ho'
正如我在 SWIG 生成的 wrap 文件中看到的,wrap 方法实际上调用了 c_str(),wrap 的代码:
jstring jresult = 0 ;
std::string result;
result = (arg1)->getSerialized();
jresult = jenv->NewStringUTF((&result)->**c_str()**);
return jresult;
因此,正如预期的那样,Java 中收到的 String 会被截断。那么我如何更改(大概)我的 %extend 函数包装器,以便我可以将其作为字节数组(byte [])返回,而无需事先知道数组的长度。如果可以在 SWIG 层中创建 byteArray 那就太好了,这样我就可以从 Java 调用该方法,例如:
byte[] serialized = mc.getSerialized("test");
其他注意事项:给出了使用 std::string 存储二进制数据,以及使用 Google protobuf 库C++ protobuf 用法的返回类型
有一个非常相似的问题,包括标题Swig: convert return type std::string to java byte[]但是没有二进制数据的情况,所以这里给出的解决方案不适用。
使用 SWIG 2。