17

对于一个简单的 proto 文件:

消息人{
  必需的 int32 id = 1;
  所需的字符串名称 = 2;
  可选字符串电子邮件 = 3;
}

它由 protoc.exe 编译,结果用于一个同样简单的测试项目,除了包含 protoc 生成的文件之外,它基本上什么都不做。

我正在使用 msvc10 构建测试项目(x64),然后它给了我很多警告:

警告 1 警告 C4244: 'return' : 从 '__int64' 转换为 'int',可能丢失数据 D:\Work\protobuf-trunk\src\google\protobuf\descriptor.h 1441 1 testProtobuf
...
警告 11 警告 C4267:'argument':从 'size_t' 转换为 'int',可能丢失数据 D:\Work\protobuf-trunk\src\google\protobuf\unknown_field_set.h 142 1 testProtobuf
警告 12 警告 C4267:'return':从 'size_t' 转换为 'int',可能丢失数据 D:\Work\protobuf-trunk\src\google\protobuf\unknown_field_set.h 237 1 testProtobuf
...
警告 14 警告 C4244:'=':从 '__int64' 转换为 'int',可能丢失数据 D:\Work\protobuf-trunk\src\google\protobuf\io\coded_stream.h 902 1 testProtobuf
警告 15 警告 C4244:'return':从 '__int64' 转换为 'int',可能丢失数据 D:\Work\protobuf-trunk\src\google\protobuf\io\coded_stream.h 1078 1 testProtobuf
警告 16 警告 C4267:'argument':从 'size_t' 转换为 'google::protobuf::uint32',可能丢失数据 D:\Work\protobuf-trunk\src\google\protobuf\wire_format_lite_inl.h 663 1 testProtobuf
...
警告 19 警告 C4267:'return':从 'size_t' 转换为 'int',可能丢失数据 D:\Work\protobuf-trunk\src\google\protobuf\wire_format_lite_inl.h 739 1 testProtobuf
警告 20 警告 C4267:'argument':从 'size_t' 转换为 'google::protobuf::uint32',可能丢失数据 D:\Work\protobuf-trunk\src\google\protobuf\wire_format_lite_inl.h 742 1 testProtobuf
警告 21 警告 C4267:'return':从 'size_t' 转换为 'int',可能丢失数据 D:\Work\protobuf-trunk\src\google\protobuf\wire_format_lite_inl.h 743 1 testProtobuf
警告 22 警告 C4267:'argument':从 'size_t' 转换为 'int',可能丢失数据 D:\Work\testProtobuf\testProtobuf\person.pb.cc 211 1 testProtobuf
...
警告 28 警告 C4996:'std::_Copy_impl':带有可能不安全参数的函数调用 - 此调用依赖于调用者检查传递的值是否正确。要禁用此警告,请使用 -D_SCL_SECURE_NO_WARNINGS。请参阅有关如何使用 Visual C++ 'Checked Iterators' C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xutility 2239 1 testProtobuf 的文档
警告 29 警告 C4996:'std::_Copy_impl':带有可能不安全参数的函数调用 - 此调用依赖于调用者检查传递的值是否正确。要禁用此警告,请使用 -D_SCL_SECURE_NO_WARNINGS。请参阅有关如何使用 Visual C++ 'Checked Iterators' C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xutility 2239 1 testProtobuf 的文档

有什么好的方法来解决所有这些警告吗?任何建议将不胜感激。

附言。libprotobuf 项目本身可以由 msvc10 干净编译而不会发出任何警告。

[编辑 2013/02/20 ]

工作解决方案:

  1. 为那些 protoc 生成的 .cc 文件设置属性:
    配置属性 -> c/c++ -> 高级 -> 禁用特定警告
4

4 回答 4

7

一种简单的方法是使用包装头来包含生成的 protobuf 头:

#ifndef MESSAGES_WRAPPER_H
#define MESSAGES_WRAPPER_H

#ifdef _MSC_VER
  #pragma warning(push)
  #pragma warning(disable: 4018 4100 4267)
#endif

#include "messages.pb.h"

#ifdef _MSC_VER
  #pragma warning(pop)
#endif

#endif // MESSAGES_WRAPPER_H
于 2019-08-23T09:37:37.860 回答
5

您可以破解 protoc 编译器的源代码,让它自动将 pragma 注入生成的文件中。

src/google/protobuf/compiler/cpp/cpp_file.ccGenerateHeader(io::Printer* printer)第 94 行左右,将第一个printer->Print调用更改为:

  // Generate top of header.
  printer->Print(
    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
    "// source: $filename$\n"
    "\n"
    "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
    "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
    "\n"
    "#ifdef _MSC_VER\n"
    "#  pragma warning(push)\n"
    "#  pragma warning(disable: 4127 4244 4267)\n"
    "#endif\n"
    "\n"
    "#include <string>\n"
    "\n",
    "filename", file_->name(),
    "filename_identifier", filename_identifier);

然后在第294 行附近的同一函数的末尾,将最后一次printer->Print调用更改为:

  printer->Print(
    "#ifdef _MSC_VER\n"
    "#  pragma warning(pop)\n"
    "#endif\n"
    "\n"
    "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
    "filename_identifier", filename_identifier);

现在您只需要编译 protoc 目标并运行新的 protoc.exe 以在生成的标头中包含 pragma。

于 2013-02-21T05:57:56.410 回答
1

由于维护负担,我不太喜欢破解 protoc 源,所以我想出了更简单的解决方案。

您可能已经使用某种脚本生成文件,因为您需要将许多参数传递给 protoc,因此进一步自定义此脚本非常容易。

我创建了 powershell 脚本,它对生成的文件进行后处理#include "Grpc.Header.h",并在生成文件的开头和#include "Grpc.Footer.h"所述文件的结尾添加。然后,您可以在放置在项目中时自定义这些头文件。除了用 禁用警告之外#pragma warning,我还可以在需要时轻松引入其他更改。

注意:在这个例子中,我生成#define了我的项目需要的额外内容,以及对 MSVC 很好的预编译头文件支持。我将其留在示例中以说明您可以做什么,但可以安全地删除它。dllexport_decl=MYAPI允许在您的 dll 项目中导出 protobuf 类。

生成原型.ps1

$ProjectDirectory = "My\Project\Directory\"
$ProtoDirectory = "My\Proto\Directory"

protoc --proto_path=$ProtoDirectory --cpp_out=dllexport_decl=MYAPI:$ProjectDirectory universe.proto

$Plugin = where.exe grpc_cpp_plugin

protoc --proto_path=$ProtoDirectory --grpc_out=$ProjectDirectory --plugin=protoc-gen-grpc=$Plugin universe.proto

foreach($File in Get-ChildItem $ProjectDirectory* -Include *.pb.cc, *.pb.h )
{
    $Content = Get-Content $File

    if( $File.FullName.EndsWith(".cc"))
    {
        Set-Content $File "#include `"pch.h`""
        Add-Content $File "#include `"Grpc.Header.h`""
    }
    else
    {
        Set-Content $File "#include `"Grpc.Header.h`""
    }

    Add-Content $File $Content
    Add-Content $File "#include `"Grpc.Footer.h`""
}

Grpc.Header.h

#pragma warning(push)
#pragma warning(disable: 4251)

#ifdef API_EXPORT
#  define MYAPI __declspec(dllexport)
#else
#  define MYAPI __declspec(dllimport)
#endif

Grpc.Footer.h

#pragma warning(pop)
于 2021-12-28T12:33:39.943 回答
-3

编译器向您发出这些警告是正确的,因为存在截断的风险。

如果转换是安全的,请使用显式转换。这比盲目禁用警告更干净。

于 2019-08-23T09:40:36.970 回答