简体   繁体   English

C结构(C++ POD)和谷歌protobufs之间的转换?

[英]Conversion between C structs (C++ POD) and google protobufs?

I have code that currently passes around a lot of (sometimes nested) C (or C++ Plain Old Data) structs and arrays.我的代码当前传递了很多(有时是嵌套的)C(或 C++ 普通旧数据)结构和数组。

I would like to convert these to/from google protobufs.我想将这些转换为/从谷歌 protobufs 转换。 I could manually write code that converts between these two formats, but it would be less error prone to auto-generate such code.我可以手动编写在这两种格式之间转换的代码,但自动生成这样的代码不太容易出错。 What is the best way to do this?做这个的最好方式是什么? (This would be easy in a language with enough introspection to iterate over the names of member variables, but this is C++ code we're talking about) (这在具有足够内省以迭代成员变量名称的语言中很容易,但这是我们正在谈论的 C++ 代码)

One thing I'm considering is writing python code that parses the C structs and then spits out a .proto file, along with C code that copies from member to member (in either direction) for all of the types, but maybe there is a better way... or maybe there is another IDL that already can generate:我正在考虑的一件事是编写解析 C 结构然后输出 .proto 文件的 python 代码,以及从成员到成员(在任一方向)复制所有类型的 C 代码,但也许有一个更好的方法......或者也许已经可以生成另一个 IDL:

  1. .h file containing all of nested types .h 文件包含所有嵌套类型
  2. .proto file containing equivalents .proto 文件包含等价物
  3. .c file with functions that copy either direction between the C++ structs that the .proto file generates and the structs defined in the .h file .c 文件,其中包含在 .proto 文件生成的 C++ 结构和 .h 文件中定义的结构之间复制任一方向的函数

Protocol buffers can be built by parsing an ASCII representation using TextFormat .可以通过使用TextFormat解析 ASCII 表示来构建协议缓冲区。 So one option would be to add a method dumpAsciiProtoBuf to each of your structs.因此,一种选择是将方法dumpAsciiProtoBuf添加到每个结构中。 The method would dump any simple fields (like strings, bools, etc) and call dumpAsciiProtoBuf recursively on nested structs fields.该方法将转储任何简单字段(如字符串、布尔值等)并在嵌套结构字段上递归调用dumpAsciiProtoBuf You would then have to make sure that the concatenated result is a valid ASCII protocol buffer which can be parsed using TextFormat .然后,您必须确保连接的结果是可以使用TextFormat解析的有效 ASCII 协议缓冲区。

Note though that this might have some performance implications (since parsing the ASCII representation could be expensive).请注意,这可能会对性能产生一些影响(因为解析 ASCII 表示可能很昂贵)。 However, this would save you the trouble of writing a converter in a different language, so it seems to be a convenient solution.但是,这样可以省去用不同语言编写转换器的麻烦,所以这似乎是一个方便的解决方案。

I could not find a ready solution for this problem, if there is one, please let me know!我找不到解决此问题的现成解决方案,如果有,请告诉我!

If you decide to roll your own in python, the python bindings for gdb might be useful.如果您决定在 python 中自己开发,gdb 的 python 绑定可能会很有用。 You could then read the symbol table, find all structs defined in specified file, and iterate all struct members.然后,您可以读取符号表,查找指定文件中定义的所有结构,并迭代所有结构成员。 Then use <gdbtype>.strip_typedefs() to get the primitive type of each member and translate it to appropriate protobuf type.然后使用<gdbtype>.strip_typedefs()获取每个成员的原始类型并将其转换为适当的 protobuf 类型。

This is probably safer then a text parsers as it will handle types that depends on architecture, compiler flags, preprocessor macros, etc.这可能比文本解析器更安全,因为它将处理依赖于架构、编译器标志、预处理器宏等的类型。

I guess the code to convert to and from protobuf also could be generated from the struct member to message field relation, but does not sound easy.我猜想从 struct 成员到消息字段的关系也可以生成与 protobuf 相互转换的代码,但听起来并不容易。

I would not parse the C source code myself, instead I would use the LibClang to parse C files into an AST and my own AST walker to generate the Protobuf and the transcoders as necessary.我不会自己解析 C 源代码,而是使用LibClang将 C 文件解析为AST和我自己的 AST walker 以根据需要生成Protobuf和转码器。 Googling for "libclang walk AST" should give something to start with, like ast-walker.cc and ast-dumper.cc from this github repository , for example.谷歌搜索“libclang walk AST”应该提供一些开始,例如来自这个 github 存储库ast-walker.ccast-dumper.cc

The question brought up is the age old challenge with "C" (and C++) code - No easy (or standard) way to reflect on c "struct" (or classes).提出的问题是“C”(和 C++)代码的古老挑战 - 没有简单(或标准)的方式来反映 c“结构”(或类)。 Just search stack overflow on C reflection, and you will see lot of unsuccessful attempts.只需在 C 反射上搜索堆栈溢出,您就会看到很多不成功的尝试。 My first advice will be NOT to try to build another solution (in python, etc.).我的第一个建议是不要尝试构建另一个解决方案(在 python 等中)。

One simple approach: Consider using gdb ptype to get structured output for you structures, which you can use to create the .proto file.一种简单的方法:考虑使用 gdb ptype 为您的结构获取结构化输出,您可以使用它来创建 .proto 文件。 The advantage is that there is no need to handle the full syntax of the C language (#define, line breaks, ...).优点是无需处理 C 语言的完整语法(#define、换行符……)。 See How do I show what fields a struct has in GDB?请参阅如何显示结构在 GDB 中具有哪些字段?

From the gdb ptype, it's a short trip to protobuf '.proto' file.从 gdb ptype 到 protobuf '.proto' 文件的短途旅行。

You can get similar result from libCLang (and I believe there is comparable gcc plugin, but I can not locate it).你可以从 libCLang 得到类似的结果(我相信有类似的 gcc 插件,但我找不到它)。 However, you will have to write some non-trivial "C" code.但是,您将不得不编写一些重要的“C”代码。

Another approach - will be to use 'swig' ( https://www.swig.org ), and process the swig xml output (or the -xmlout option) to dump the parse tree into XML.另一种方法 - 将使用“swig”( https://www.swig.org ),并处理 swig xml 输出(或 -xmlout 选项)以将解析树转储为 XML。 While this approach will require a little bit of digging to locate the structure that are needed, the information in XML format is complete, easy to parse (using whatever XML parser you want - python, perl).虽然这种方法需要一些挖掘来定位所需的结构,但 XML 格式的信息是完整的,易于解析(使用您想要的任何 XML 解析器 - python、perl)。 If you are brave enough, you can use xslt to generate the output.如果你足够勇敢,你可以使用 xslt 来生成输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM