Protobuf问题
Protobuf问题
该文记录使用 Protobuf
问题。
Protobuf问题
1. 动态链接
Google
默认编译模式是静态库,可以在 cmake-gui
中勾选 protobuf_BUILD_SHARED_LIBS
编译成动态库
自己项目使用时还需要设置宏 PROTOBUF_USE_DLLS
指定使用 protobuf
动态库
1
add_compile_definitions(PROTOBUF_USE_DLLS)
2. proto 文件已存在1
问题的详细信息如下
1
2
3
4
5
[libprotobuf ERROR google/protobuf/descriptor_database.cc:58] File already exists in database: address.proto
[libprotobuf FATAL google/protobuf/descriptor.cc:1358] CHECK failed: GeneratedDatabase()->Add(encoded_file_descriptor, size):
terminate called after throwing an instance of 'google::protobuf::FatalException'
what(): CHECK failed: GeneratedDatabase()->Add(encoded_file_descriptor, size):
Aborted (core dumped)
这个错误原因是因为在两个编译目标(共享库或者可执行文件)中都引入了相同的 *.pb.cc
文件。
最常规的解决办法就是把所有 address.proto
生成的 address.pb.h
和 address.pb.cc
编译成一个共享库 address.dll
,然后其他要使用的工程都去链接这个共享库。
值得注意的是这样做就需要导入导出符号,需要进行以下修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 设置 protobuf 目录
if(CMAKE_CXX_PLATFORM_ID MATCHES "Windows")
set(CMAKE_PREFIX_PATH "C:\\Program Files\\protobuf")
elseif(CMAKE_CXX_PLATFORM_ID MATCHES "Linux")
set(CMAKE_PREFIX_PATH "")
endif()
macro(AddProtobufInc)
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIRS})
# 关键在这里,通过 EXPORT_MACRO 设置导入导出宏为 PROTO_EXPORT
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS "address.proto"
EXPORT_MACRO "PROTO_EXPORT"
)
endmacro()
macro(AddProtobufLib)
add_compile_definitions(PROTOBUF_USE_DLLS)
# 编译成动态库时设置为导出宏,Windows 导入导出不一样
if(CMAKE_CXX_PLATFORM_ID MATCHES "Windows")
add_compile_definitions(PROTO_EXPORT=__declspec\(dllexport\))
elseif(CMAKE_CXX_PLATFORM_ID MATCHES "Linux")
add_compile_definitions(PROTO_EXPORT=__attribute__\(\(visibility\("default"\)\)\))
endif()
target_link_libraries(${PROJECT_NAME} ${Protobuf_LIBRARIES})
endmacro()
其他工程链接 address.dll
也需要设置为导入宏
1
2
3
4
5
6
# 其他工程链接时设置为导入宏,Windows 导入导出不一样
if(CMAKE_CXX_PLATFORM_ID MATCHES "Windows")
add_compile_definitions(PROTO_EXPORT=__declspec\(dllimport\))
elseif(CMAKE_CXX_PLATFORM_ID MATCHES "Linux")
add_compile_definitions(PROTO_EXPORT=__attribute__\(\(visibility\("default"\)\)\))
endif()
参考
本文由作者按照 CC BY 4.0 进行授权