protobuf 在通过 hidl 接口传输时,是不是应该用 string 啊

2019-08-13 17:24:02 +08:00
 amiwrong123

在 Android 的 java 层往 native 层的一个 service 传输一个 protobuf 的字符串: 首先 proto 文件( information )很简单:

syntax = "proto2";
option optimize_for = LITE_RUNTIME;
message info {
    optional int32  member = 1;
}

mk 里面分别编译了 java 库和 c++库:

include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
    $(call all-proto-files-under, proto) \

LOCAL_MODULE := xxx

LOCAL_MODULE_TAGS := optional

LOCAL_VENDOR_MODULE := true

#LOCAL_PROTOC_OPTIMIZE_TYPE := nano

LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/

LOCAL_SHARED_LIBRARIES := liblog

include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
    $(call all-proto-files-under, proto) \

LOCAL_MODULE := xxx.aaa.bbb

LOCAL_MODULE_TAGS := optional

LOCAL_VENDOR_MODULE := true

#LOCAL_PROTOC_OPTIMIZE_TYPE := nano

LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/

include $(BUILD_STATIC_JAVA_LIBRARY)

在 java 层时这么塞数据的:

information.info data = information.info();
data.member = 150;
String buf = new String(information.info.toByteArray(data));
//然后通过 hidl 接口传过去

在 c++层这么解数据的:

info data;
data.ParseFromString(buf);

现在问题是,当我在 info 的 member 赋值 127 以上的数字时,就会出错,c++层解析出来变成 2 万多,127 或以下的值就没有问题。是我在塞数据的时候用错了吗?

(还有一点 proto 文件自动生成的 java 文件是继承的 messagenano,而生成的 c++代码继承的是 messagelite,这两个好像不一样啊)

1805 次点击
所在节点    程序员
7 条回复
amiwrong123
2019-08-13 19:35:23 +08:00
自己顶一下,话说我这帖子是不是应该发在安卓区…
amiwrong123
2019-08-13 19:55:34 +08:00
mk 文件里面,这个 LOCAL_PROTOC_OPTIMIZE_TYPE := nano 是没有注释掉的,忘改了。
Monad
2019-08-13 20:55:39 +08:00
lz 在 cxx 层十六进制输出一下 buf 看看呢 只有一个字段的话 人肉很好解析的
amiwrong123
2019-08-14 14:10:33 +08:00
@Monad
谢谢,现在感觉应该是 String buf = new String(information.info.toByteArray(data));有问题,因为这句对字符串编码时用的是 UTF-8,这是一个字符对应两个字节的,而我应该用"ISO-8859-1"编码方法,这是一个字符对应一个字节的。
Monad
2019-08-14 14:15:53 +08:00
@amiwrong123 #4 Protobuf 的 string 是要求必须为 UTF-8 编码的 如果非 UTF-8 编码应该用 bytes 哈. 虽然内部表示是一样的 但是解析的库可能会报错.
建议还是在 C++层 Hexdump 一下 贴上来好分析.
amiwrong123
2019-08-14 14:31:10 +08:00
@Monad
“ Protobuf 的 string 是要求必须为 UTF-8 编码”,是这样的吗,我在官网上好像没看到这句话。

反正现在比较尴尬,

java 的序列化相关方法是(用字节数组):
byte[] toByteArray();: serializes the message and returns a byte array containing its raw bytes.
static Person parseFrom(byte[] data);: parses a message from the given byte array.

c++的序列化相关方法是(用 string ):
bool SerializeToString(string* output) const;: serializes the message and stores the bytes in the given string. Note that the bytes are binary, not text; we only use the string class as a convenient container.
bool ParseFromString(const string& data);: parses a message from the given string.

所以我感觉是字节数组转字符串的时候出了问题,等会我打印出来看看。。
Monad
2019-08-14 17:12:06 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/591576

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX