当前位置: 首页 > 知识库问答 >
问题:

Swig:将返回类型std::string(二进制)转换为java字节[]

淳于升
2023-03-14

我的情况是,我有一个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";

因此,可以使用类似Java的方法:

MyClass mc = new MyClass();
String res = mc.getSerialized("test");

但现在我遇到了一个问题,序列化的std::字符串包含二进制数据,包括表示C字符串结尾的“\0”字符,实际上以下代码显示了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\u str(),wrap的代码:

jstring jresult = 0 ;
std::string result;
result = (arg1)->getSerialized();
jresult = jenv->NewStringUTF((&result)->**c_str()**); 
return jresult;

因此,正如预期的那样,Java中接收到的字符串会被截断。那么,我如何(大概)更改我的%扩展函数包装器,以便可以将其作为字节数组(byte[])返回,而不必事先知道数组的长度。如果可以在SWIG层中创建byteArray,那就太好了,因此我可以从Java调用该方法,如:

byte[] serialized = mc.getSerialized("test");

其他注意事项:给出了std::字符串用于存储二进制数据的使用,以及使用谷歌协议库C协议使用的返回类型

有一个非常类似的问题,包括标题Swig:convert return type std::string to java byte[],但没有二进制数据的情况,因此这里给出的解决方案不适用。

使用SWIG 2。

共有1个答案

东门彬
2023-03-14

你可以用一些打字地图和一些JNI来做你想做的事情。我举了一个例子:

%module test

%include <std_string.i>

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

它指出,带有的C包装器为匹配bool-foo的函数返回一个Java字节数组。它还设置了一个临时的std::string,以实现真正的foo实现,从而对Java接口本身隐藏输入参数。

调用完成后,如果函数没有返回false,它将创建并返回一个字节数组。

我检查了以下各项,以确保一切正常:

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

您应该知道从c_str()的返回类型强制转换到const jbyte*的含义-它可能并不总是您想要的。

另一种选择是,如果输出字节数组的大小实际上是固定的,或者是不可预测的,那么可以将其作为预先分配的输入来传递。这将起作用,因为数组首先通过引用有效地传递到函数中。

 类似资料:
  • 问题内容: 我正在尝试将字节值转换为二进制以进行数据传输。基本上,我要在字节数组(“ 10101100”是单个字节)中以二进制(“ 10101100”)的形式发送类似“ AC”的值。我希望能够接收此字节并将其转换回“ 10101100”。截至目前,我还没有成功,完全不知道从哪里开始。任何帮助都会很棒。 编辑 :对所有混乱,抱歉,我没有意识到我忘记添加特定的细节。 基本上,我需要使用字节数组通过套接

  • 假设我有以下字符串: 如何将其转换为二进制数(0和1)?诀窍在于:我不允许使用内置方法进行转换。这必须用数学方法来完成。我不知道从哪里开始。谁能给我指出正确的方向吗? 编辑1:我看过这个问题,人们建议使用getBytes(字符串)、字符集UTF-8,我nteger.toBinaryString。我不允许使用任何这些方法进行转换。我也没听说过36垒。

  • 我如何将一个写为二进制的字符串转换为二进制(字节数组)? 如果我有一个字符串: 下面是当我将二进制设置为字节数组时发生的情况(字节数组返回48,这是ASCII) 我不擅长解释,所以希望上面的例子足以告诉你我想要什么。

  • 问题内容: 因此,我尝试将Key转换为字符串,以便可以使用System.out显示它,然后将其转换回Key。我可以使用BASE64Encoder将其转换为字符串,但是在将其转换回时遇到问题。这是我的源代码: 问题答案: 您永远不会使用un-base-64您的字符串。 替换为: 与

  • 我希望代码得到一个int作为参数,如果年龄是奇数,则加3,如果是偶数,则加2,然后作为字符串返回。 有了这个代码我得到了 不兼容的类型:无法将int转换为字符串 九号线不是已经换了吗?

  • 方法(下面)是一个类型,我用作参数的类是一个。我想知道我选角的方式是否管用: 这就是方法: 此URL指向类: 我把它放进了粘贴箱,因为课程太长了。