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

无法编译协议生成的(C)类

祁曦哲
2023-03-14

我目前在编译protobuf生成的C代码时遇到了一些问题<代码>协议(code>protoc)运行正常,不会显示任何警告,但是,当我尝试编译生成的C代码以便构建静态库时,g向我显示以下消息:

CanInfo。pb。抄送:107:5:错误:“::protobuf\u BusType\u 2eproto”尚未声明107;::protobuf\u BusType\u 2eproto::AddDescriptors();

到目前为止,我能够收集到的是,这是我的BusType枚举的一些问题,它看起来像这样:

syntax = "proto3";

package MyPackage;

enum BusType {

    ProprietaryBus = 0;
    OpenBus = 1;
    UnknownBus = 2;

}

此枚举包含在一条名为CanInfo的消息中,该消息如下所示:

syntax = "proto3";

package MyPackage;

import "BusType.proto";

message CanInfo {

    int32 interfaceId = 10;
    bool isConnected = 20;
    BusType busType = 30;

}

正如我前面提到的,protoc“正确”(无错误)编译这些文件。用于编译protos的版本是protoc 3.6.0。这是protoc生成的C代码部分:

::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
      descriptor, 248);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
    "data_containers/device_data/CanInfo.proto", &protobuf_RegisterTypes);
::protobuf_BusType_2eproto::AddDescriptors();
//           ^ error occurs here

在代码中搜索,唯一提到protobuf\u BusType\u 2eproto的名称空间是上面的一行。用于编译C代码的编译器版本是powerpc-linux-gnu-g-6(Ubuntu 6.4.0-17ubuntu1)6.4.0 20180424。将G版本更改为版本8或9不会改变此行为。

我曾多次尝试清理构建目录,并尝试切换到其他protobuf版本(3.4.0),但这也导致了许多编译器错误,主要是因为protoc版本太旧。

单独构建每个文件也不会改变行为。

是什么导致了这种行为?到目前为止,我还没有遇到使用Protobuf的问题。以前有没有人经历过这种情况,并且知道一个简便的窍门?

这可能是我调用protoc的方式造成的吗?

###
# Re-compile protos
###
set(BUILD_PROTOS True)
set(PROTOBUF_COMPILER protoc)
if (BUILD_PROTOS)
    function(BUILD_PROTOS)
        foreach(PROTO ${PROTOS})
            message("Compiling ${PROTO}...")
            execute_process(
                COMMAND ${PROTOBUF_COMPILER} ${PROTO_DIRS} "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" ${PROTO}
                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
            )
        endforeach()
    endfunction()

    ###
    # Compile all protos
    ###
    BUILD_PROTOS()
endif()

共有1个答案

戈巴英
2023-03-14

看来我已经解决了这个问题。显然,protoc编译器中存在一个bug,每次编译单个文件时,将文件导入同一目录会导致这种奇怪的行为。一次编译多个文件时,protoc会产生一个错误,指出枚举值已在另一个文件中定义,并发出以下注释:

device_data/BusType.proto:15: 5:请注意,枚举值使用C范围规则,这意味着枚举值是其类型的兄弟,而不是其子级。因此,“ProprietaryBus”在“MyPackage”中必须是唯一的,而不仅仅是在“BusType”中。

谷歌搜索愈演愈烈,我看到了这篇2012年的旧谷歌代码帖子:

对于协议编译器,“bar.proto”和“x/bar.proto”是两个proto文件,尽管它们指向同一个物理文件
使用“import”x/bar.proto“是正确的修复方法。

解决方法(或修复)只是添加相对于协议工作目录的整个路径。

import "data_containers/device_data/BusType.proto";

在CMake中,现在看起来如下所示。

message("Compiling protos...")
execute_process(
  COMMAND ${PROTOBUF_COMPILER}
  ${PROTO_DIRS} "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" ${PROTOS}
  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

到目前为止,这已经解决了我的问题,如果有新的信息出现,我会编辑我的答案。也许这对其他人有用。

 类似资料:
  • 我正在学习关于协议缓冲区的google python教程,在编译器出现之前,我已经能够成功地完成所有工作。 https://developers.google.com/protocol-buffers/docs/pythontutorial 本教程内容如下: 现在运行编译器,指定源目录(应用程序的源代码所在的目录–如果不提供值,则使用当前目录)、目标目录(希望生成的代码所在的目录;通常与$SRC\

  • 我正在尝试使用Prorobuf使用RpcChannel和RpcController生成服务。我参考了谷歌Prorobuf的语言指南,并且: 我有这样的示例原始文件: 语法=“proto2”; 然后我用以下代码进行编译: 我有. h和. cc文件。但是当我搜索生成的代码时,我只找到了“请求”和“响应”的类,而没有找到“搜索服务”的类: 语言指南网页提供了一个示例(https://developers

  • 问题内容: 我grep其他主题,但他们没有帮助我=(。在我的工作服务器上,我没有sudo特权,因此我使用 ./configure –prefix = / home /用户名/本地 然后,我用“ person”示例创建源文件,并使用protoc成功地对其进行编译。 我没有pkg-info =(。我尝试用 g ++ -I / home /用户名/本地/ include -L / home /用户名/本

  • 我搜索其他主题,但它们对我没有帮助=(。在我的工作服务器上,我没有sudo特权,所以我安装PB时使用 ./配置--prefix=/home/用户名/本地 然后我用“人”例子创建源文件,并用协议成功编译。 我没有pkg信息=(。我尝试用 g-I/home/username/local/include-L/home/username/local/lib-lprotobuf-lpthread main。

  • 我使用了Jooq官方网站上的这个工具:https://github.com/etiennestuder/gradle-jooq-plugin从我的数据库生成代码。 但如果我设置

  • 我正在从事一个使用Java、C#和C应用程序的项目。为了在他们之间进行通信,我尝试使用Google协议缓冲区。我正在使用以下命令。原型文件,取自示例: 我指的是以下教程:https://developers.google.com/protocol-buffers/docs/csharptutorial 其他语言的教程也在那里。 我为每种语言尝试了以下命令行参数: Java: C:\ProtoBuf