遷移指南
v34.0 中的更改
以下是庫版本中破壞性更改的列表,以及如何更新程式碼以適應這些更改。
這涵蓋了在v34.x 新聞公告和v34.0 釋出說明中宣佈的破壞性更改。
C++ 的變更
C++ 在 7.34.0 版本中將其主版本號提升至 7。6.33 是 6.x 系列的最後一個次要版本。
刪除未來宏
以下用於破壞性更改分階段推出的宏已被刪除,其行為現在是預設行為
PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORTPROTOBUF_FUTURE_REMOVE_ADD_IGNORE_CRITERIAPROTOBUF_FUTURE_STRING_VIEW_DESCRIPTOR_DATABASEPROTOBUF_FUTURE_NO_RECURSIVE_MESSAGE_COPYPROTOBUF_FUTURE_REMOVE_REPEATED_PTR_FIELD_ARENA_CONSTRUCTORPROTOBUF_FUTURE_REMOVE_MAP_FIELD_ARENA_CONSTRUCTORPROTOBUF_FUTURE_REMOVE_REPEATED_FIELD_ARENA_CONSTRUCTOR
新的 RepeatedPtrField 佈局
RepeatedPtrField 已轉換為新的內部元素佈局,其中元素儲存在預分配記憶體的連續塊中,類似於 std::deque。這導致一些 API 的複製/移動語義發生了一些變化,並且一些 UnsafeArena API 可能會成為其 arena-safe 對應物的函式等價物並被棄用。
RepeatedField::Get 和 RepeatedPtrField::Get 上的 MSB 硬化檢查
透過為重複欄位訪問新增全面的邊界檢查,Protobufs 針對 OOB 錯誤進行了強化。
從 Repeated/Map 欄位中刪除啟用 Arena 的建構函式
RepeatedField(Arena*)、RepeatedPtrField(Arena*) 和 Map(Arena*) 建構函式已被刪除。
移除已棄用的 API
我們刪除了以下公共執行時 API。
AddUnusedImportTrackFile() 和 ClearUnusedImportTrackFiles()
API: AddUnusedImportTrackFile(), ClearUnusedImportTrackFiles()
替代: AddDirectInputFile() 和 ClearDirectInputFiles()
來自訊息差異器的 AddIgnoreCriteria
PROTOBUF_FUTURE_REMOVE_ADD_IGNORE_CRITERIA 是為破壞性更改而新增的。我們刪除了該宏。
API: AddIgnoreCriteria()
替代: 將原始指標包裝在 unique_ptr 中。
FieldDescriptor::has_optional_keyword()
API: FieldDescriptor::has_optional_keyword()
替代: has_presence()
FieldDescriptor::label()
API: FieldDescriptor::label()
替代: is_repeated() 或 is_required()
FieldDescriptor::is_optional()
API: FieldDescriptor::is_optional()
替代: !is_required() && !is_repeated()
UseDeprecatedLegacyJsonFieldConflicts()
API: UseDeprecatedLegacyJsonFieldConflicts()
替代: 無替代。
更嚴格的名稱長度限制
Protobuf 編譯器對欄位名稱等符號名稱的長度實施了更嚴格的限制,以防止潛在問題。如果任何欄位名稱的長度 > 2^16,則會生成錯誤。
在 CMake 中隱藏私有生成器標頭檔案
protoc 生成器標頭檔案不再由 CMake 安裝。這不應影響大多數使用者。
邏輯常量操作上的 [[nodiscard]]
[[nodiscard]] 已新增到多個邏輯常量 protobuf API 中,如果未能使用返回的值,則表明可能存在錯誤。這遵循 C++ 標準庫中常用的模式。
Python 中的變更
Python 在 7.34.0 版本中將其主版本號提升至 7。6.33 是 6.x 系列的最後一個次要版本。
放棄 Python 3.9 支援
支援的最低 Python 版本是 3.10。使用者應升級。
放寬毒丸警告
我們放寬了毒丸。對於 7.34.x 的舊生成檔案,不再發出警告或錯誤。
在不正確的 Timestamp 或 Duration 轉換時引發 TypeError
現在,當將不正確的型別轉換為 Timestamp 或 Duration 時,我們不再引發 AttributeError,而是引發 TypeError。
拒絕布林值轉換為列舉和 int 欄位
我們現在拒絕將布林值設定為 enum 或 int 欄位。API 會引發錯誤而不是隱式轉換它們。
從 json_format 中刪除 float_precision
我們從 json_format 序列化器中刪除了已棄用的 float_precision 選項。此選項不存在於其他 ProtoJSON 序列化器中,並且具有令人困惑的語義。
從 text_format 中刪除 float_format/double_format
我們從 text_format 中刪除了已棄用的 float_format 和 double_format 選項。這些選項在其他 proto 文字格式序列化器中不可用。
已刪除的已棄用 API
我們刪除了以下公共執行時 API。
FieldDescriptor.label
API: FieldDescriptor.label
替代: is_repeated() 或 is_required()
PHP 中的更改
PHP 在 5.34.0 版本中將其主版本號提升至 5。4.33 是 4.x 系列的最後一個次要版本。
放棄 PHP 8.1 支援
支援的最低 PHP 版本是 8.2。使用者應升級。
已刪除的已棄用 API
我們刪除了以下公共執行時 API。
FieldDescriptor getLabel
API: FieldDescriptor getLabel
替代: isRepeated() 或 isRequired()
Google\Protobuf\Field_Kind
API: Google\Protobuf\Field_Kind
替代: Google\Protobuf\Field\Kind
Google\Protobuf\Field_Cardinality
API: Google\Protobuf\Field_Cardinality
替代: Google\Protobuf\Field\Cardinality
Google\Protobuf\Internal\RepeatedField
API: Google\Protobuf\Internal\RepeatedField
替代: Google\Protobuf\RepeatedField
修復預設值被靜默忽略的問題
PHP 執行時已修復,以在 proto2 和 editions 中的標量欄位上遵循預設值,而不是靜默忽略它們。
型別檢查對齊
純 PHP 和 upb-PHP 實現的型別檢查已對齊。值得注意的是,純 PHP 現在拒絕字串欄位的 null,與 upb-PHP 的行為匹配。
Objective-C 中的變更
Objective-C 在 5.34.0 版本中將其主版本號提升至 5。4.33 是 4.x 系列的最後一個次要版本。
可空性註解
某些 GPB*Dictionary API 的可空性註解已更正,以標記 API 何時可以返回 nil。這導致 Swift 程式碼獲得 Swift Optional。對於 Objective-C 呼叫者,註解更正不太可能對原始碼產生任何影響。
已刪除的已棄用 API
我們刪除了以下公共執行時 API。
GPBFieldDescriptor optional
API: -[GPBFieldDescriptor optional]
替代: !required && fieldType == GPBFieldTypeSingle
其他變更
放棄 Bazel 7 支援
支援的最低 Bazel 版本是 8,這將預設從 WORKSPACE 更改為 Bzlmod。使用者應升級到 Bazel 8 或更高版本並遷移到 Bzlmod。
Bazel:刪除已棄用的 ProtoInfo.transitive_imports
ProtoInfo 中已棄用的 transitive_imports 欄位已刪除。使用者應遷移到 transitive_sources。
刪除 protobuf_allow_msvc 標誌並繼續支援 Bazel+MSVC
由於 Bazel 在 Windows 上的最新改進,我們現在繼續支援 Bazel+MSVC。--define=protobuf_allow_msvc 標誌已刪除。
v30.0 中的更改
以下是庫版本中破壞性更改的列表,以及如何更新程式碼以適應這些更改。
這涵蓋了在v30.x 新聞公告和v30.0 釋出說明中宣佈的破壞性更改。
C++ 的變更
將 CMake 子模組替換為獲取的依賴項
以前,我們的預設 CMake 行為是使用 Git 子模組來獲取固定的依賴項。指定 -Dprotobuf_ABSL_PROVIDER=package 會將我們的 CMake 配置翻轉為查詢 Abseil 的本地安裝(jsoncpp 和 gtest 也有類似選項)。這些選項不再存在,預設行為是首先查詢所有依賴項的安裝,如果需要,再從 GitHub 獲取固定版本。
要防止任何回退獲取(類似於舊的 package 行為),您可以呼叫 CMake,如下所示
cmake . -Dprotobuf_LOCAL_DEPENDENCIES_ONLY=ON
要始終從固定版本獲取依賴項(類似於舊的預設行為),您可以呼叫 CMake,如下所示
cmake . -Dprotobuf_FORCE_FETCH_DEPENDENCIES=ON
string_view 返回型別
以下描述符 API 的返回型別現在是 absl::string_view,這節省了記憶體
MessageLite::GetTypeNameUnknownField::length_delimited- 描述符 API 名稱函式,例如
FieldDescriptor::full_name
我們預計未來的破壞性版本將繼續將其他 API 遷移到 absl::string_view。
在大多數情況下,您應該嘗試在安全的情況下更新型別以使用 absl::string_view,或者在需要時顯式複製到原始型別。如果函式返回此值,您可能還需要更新呼叫者。
如果受影響的 API 方法返回的字串用作
| 型別 | 遷移 |
|---|---|
| 顯式轉換為 或者,切換到效能更好的 |
| 遷移到 如果不可行(例如由於大量依賴項),複製到 |
| 如果可空,遷移到 否則,遷移到 呼叫 |
對於常見的容器和其他 API,您可能可以遷移到與 absl::string_view 相容的變體。以下是一些常見示例。
| 類別 | 遷移前 | 遷移 |
|---|---|---|
插入到 std::vector 中 |
|
|
| 對映或集的插入 |
|
|
| 對映或集的查詢 |
| 遷移到 Abseil 容器。 或者,定義一個透明比較器。
|
| 字串連線 |
|
無論如何,出於效能原因都推薦這些。參見 https://abseil.io/tips/3。 |
另請參見 https://abseil.io/tips/1,獲取有關使用 absl::string_view 的一般提示。
停用 MSVC + Bazel
Windows 上的 Bazel 使用者應切換到使用 clang-cl,方法是將以下內容新增到其專案中,例如此示例。
.bazelrc
common --enable_platform_specific_config build:windows
--extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows-clang-cl
--extra_execution_platforms=//:x64_windows-clang-cl
MODULE.bazel
bazel_dep(name = "platforms", version = "0.0.10")
bazel_dep(name = "rules_cc", version = "0.0.17")
# For clang-cl configuration
cc_configure = use_extension("@rules_cc//cc:extensions.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc")
WORKSPACE
load("//:protobuf_deps.bzl", "PROTOBUF_MAVEN_ARTIFACTS", "protobuf_deps")
protobuf_deps()
load("@rules_cc//cc:repositories.bzl", "rules_cc_dependencies", "rules_cc_toolchains")
rules_cc_dependencies()
rules_cc_toolchains()
BUILD
僅適用於需要與 Bazel 8 相容的使用者。
platform(
name = "x64_windows-clang-cl",
constraint_values = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
"@bazel_tools//tools/cpp:clang-cl",
],
)
適用於需要與 Bazel 7 和 8 相容的使用者。
platform(
name = "x64_windows-clang-cl",
constraint_values = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
# See https://github.com/bazelbuild/rules_cc/issues/330.
"@rules_cc//cc/private/toolchain:clang-cl",
],
)
使用者還可以透過設定選擇退出標誌 --define=protobuf_allow_msvc=true 暫時消除錯誤,直到下一個破壞性版本。
或者,希望繼續使用 MSVC 的使用者可以切換到使用 CMake。這可以透過 Visual Studio 完成,或者透過向 CMake 命令列提供 MSVC 生成器。例如
cmake -G "Visual Studio 17 2022" -A Win64 .
ctype 從 FieldDescriptor 選項中移除
我們不再從 FieldDescriptor 選項中公開 ctype。您可以使用 v28 版本中新增的 FieldDescriptor::cpp_string_type() API 來代替它。
修改除錯 API 以編輯敏感欄位
Protobuf C++ 除錯 API(包括 Protobuf AbslStringify、proto2::ShortFormat、proto2::Utf8Format、Message::DebugString、Message::ShortDebugString、Message::Utf8DebugString)已更改為編輯用 debug_redact 註解的敏感欄位;這些 API 的輸出包含每個程序的隨機字首,並且不再可由 Protobuf TextFormat 解析器解析。使用者應採用新的編輯除錯格式以滿足大多數需要人類可讀輸出的情況(例如日誌記錄),或者考慮切換到二進位制格式進行序列化和反序列化。需要舊的可反序列化格式的使用者可以使用 TextFormat.printer().printToString(proto),但這不會編輯敏感欄位,因此應謹慎使用。
在2024 年 12 月 4 日釋出的新聞文章中閱讀更多相關資訊。
已刪除的已棄用 API
我們刪除了以下公共執行時 API,這些 API 已被標記為棄用(例如 ABSL_DEPRECATED)至少一個次要或主要版本,並且已過時或已被替換。
API: Arena::CreateMessage
替代方案: Arena::Create
API: Arena::GetArena
替代方案: value->GetArena()
API: RepeatedPtrField::ClearedCount
替代方案: 遷移到 Arenas (遷移指南)。
API: JsonOptions
替代方案: JsonPrintOptions
放棄 C++14 支援
根據 Foundational C++ 支援矩陣,此版本放棄了 C++14 作為最低支援版本,並將其提高到 17。
使用者應升級到 C++17。
在 Arena 上清除 Oneof 訊息後引入 ASAN Poisoning
此更改添加了一個強化檢查,影響使用 Arenas 的 C++ protobuf。在 protobuf arena 上分配的 Oneof 訊息現在在除錯模式下被清除,並在 ASAN 模式下被 poisoning。呼叫 clear 後,將來嘗試使用該記憶體區域將在 ASAN 中導致崩潰,作為 use-after-free 錯誤。
此實現需要 C++17。
放棄我們的 C++ CocoaPods 釋出
我們放棄了自 v4.x.x 以來一直損壞的 C++ CocoaPods 釋出。C++ 使用者應直接使用我們的 GitHub 釋出。
Python 中的變更
Python 的主版本從 5.29.x 提升到 6.30.x。
放棄 Python 3.8 支援
支援的最低 Python 版本是 3.9。使用者應升級。
刪除 bazel/system_python.bzl 別名
我們刪除了舊的 bazel/system_python.bzl 別名。
請移除對 system_python.bzl 的直接引用,轉而使用 protobuf_deps.bzl。如果您需要直接引用,請使用它在 v5.27.0 中移動到的 python/dist/system_python.bzl。
欄位設定器驗證變更
Python 和 upb 的欄位設定器現在在 edition 2023 下驗證封閉列舉。用無效值更新的封閉列舉欄位會生成錯誤。
刪除已棄用的 py_proto_library 宏
protobuf.bzl 中已棄用的內部 py_proto_library Bazel 宏已刪除。它已被官方 py_proto_library 替換,後者在 v29.x 中已移至 bazel/py_proto_library 中的 protobuf。此實現以前在 v29.x 之前的 rules_python 中可用。
移除已棄用的 API
我們刪除了以下公共執行時 API,這些 API 已被標記為棄用至少一個次要或主要版本。
反射方法
API: reflection.ParseMessage, reflection.MakeClass
替代方案: message_factory.GetMessageClass()
RPC 服務介面
API: service.RpcException, service.Service, service.RpcController, and service.RpcChannel
替代方案: 從 2.3.0 版本開始,RPC 實現不應嘗試在此基礎上構建,而應提供程式碼生成器外掛,以生成特定於特定 RPC 實現的程式碼。
MessageFactory 和 SymbolDatabase 方法
API: MessageFactory.GetPrototype, MessageFactory.CreatePrototype, MessageFactory.GetMessages, SymbolDatabase.GetPrototype, SymbolDatabase.CreatePrototype, 和 SymbolDatabase.GetMessages
替代方案: message_factory.GetMessageClass() 和 message_factory.GetMessageClassesForFiles()。
GetDebugString
API: GetDebugString
替代方案
沒有替代方案。它只存在於 Python C++ 中,而該版本已不再發布。純 Python 或 UPB 不支援它。
Python map 欄位的 setdefault 行為變更
setdefault 類似於 ScalarMap 的 dict,只是鍵和值都必須設定。setdefault 被 MessageMaps 拒絕。
Python 巢狀訊息類的 __qualname__ 包含外部訊息名稱
Python 巢狀訊息類 __qualname__ 現在包含外部訊息名稱。以前,巢狀訊息的 __qualname__ 與 __name__ 結果相同,即不包含外部訊息名稱。
例如:
message Foo {
message Bar {
bool bool_field = 1;
}
}
nested = test_pb2.Foo.Bar()
self.assertEqual('Bar', nested.__class__.__name__)
self.assertEqual('Foo.Bar', nested.__class__.__qualname__) # It was 'Bar' before
Objective-C 中的變更
這是 Objective-C 的第一個破壞性版本.
Objective-C 的主版本從 3.x.x 提升到 4.30.x。
全面修改未知欄位處理 API,棄用大多數現有 API
我們棄用了 GPBUnknownFieldSet 並將其替換為 GPBUnknownFields。新型別保留了原始輸入或 API 呼叫中未知欄位的順序,以確保在訊息重新寫入時保留排序的任何語義含義。
作為此項的一部分,GPBUnknownField 型別也有 API 更改,幾乎所有現有 API 都已棄用並添加了新 API。
已棄用的屬性 API
varintListfixed32Listfixed64ListlengthDelimitedListgroupList
已棄用的修改 API
addVarintaddFixed32addFixed64addLengthDelimitedaddGroup
已棄用的初始化器 initWithNumber:。
新的屬性 API
typevarintfixed32fixed64lengthDelimitedgroup
此型別以其值中的單個欄位編號建模,而不是將給定欄位編號的所有值分組。用於建立新欄位的 API 是 GPBUnknownFields 類上的 add* API。
我們還棄用了 -[GPBMessage unknownFields]。取而代之的是,有新的 API 來提取和更新訊息的未知欄位。
已刪除的已棄用 API
我們刪除了以下公共執行時 API,這些 API 已被標記為棄用至少一個次要或主要版本。
GPBFileDescriptor
API: -[GPBFileDescriptor syntax]
替代方案: 已過時。
GPBMessage mergeFrom:extensionRegistry
API: -[GPBMessage mergeFrom:extensionRegistry:]
替代方案: -[GPBMessage mergeFrom:extensionRegistry:error:]
GPBDuration timeIntervalSince1970
API: -[GPBDuration timeIntervalSince1970]
替代方案: -[GPBDuration timeInterval]
GPBTextFormatForUnknownFieldSet
API: GPBTextFormatForUnknownFieldSet()
替代方案: 已過時 - 使用 GPBTextFormatForMessage(),它包含任何未知欄位。
GPBUnknownFieldSet
API: GPBUnknownFieldSet
替代方案: GPBUnknownFields
GPBMessage unknownFields
API: GPBMessage unknownFields 屬性
替代方案: -[GPBUnknownFields initFromMessage:]、-[GPBMessage mergeUnknownFields:extensionRegistry:error:] 和 -[GPBMessage clearUnknownFields]
刪除用於舊生成程式碼的已棄用執行時 API
此版本刪除了支援 3.22.x 版本之前 Objective-C 生成程式碼的已棄用執行時方法。當舊的生成程式碼啟動時,庫還會發出執行時日誌訊息。
API: +[GPBFileDescriptor allocDescriptorForClass:file:fields:fieldCount:storageSize:flags:]
替代方案: 使用當前版本的庫重新生成。
API: +[GPBFileDescriptor allocDescriptorForClass:rootClass:file:fields:fieldCount:storageSize:flags:]
替代方案: 使用當前版本的庫重新生成。
API: +[GPBEnumDescriptor allocDescriptorForName:valueNames:values:count:enumVerifier:]
替代方案: 使用當前版本的庫重新生成。
替代方案: 使用當前版本的庫重新生成。
API: -[GPBExtensionDescriptor initWithExtensionDescription:]
替代方案: 使用當前版本的庫重新生成。
其他變更
毒丸警告
我們更新了“毒丸”,以便為在新的滾動升級策略下工作但將在下一個主要版本更新中中斷的舊生成程式碼 + 新執行時組合發出警告。例如,Python 4.x.x 生成程式碼應適用於 5.x.x 執行時,但會警告即將對 6.x.x 執行時造成的破壞。
C# 和 Ruby 中 UTF-8 強制執行的變更
我們添加了一個修復,以使 UTF-8 強制執行在不同語言中保持一致。字串欄位中包含錯誤非 UTF-8 資料的使用者可能會更早看到 UTF-8 強制執行錯誤。
Ruby 和 PHP 在 JSON 解析中的錯誤
我們修復了根據 JSON 規範,JSON 解析數字欄位中的字串時的不一致問題。
此修復未伴隨主要版本更新,但 Ruby 和 PHP 現在會對數字欄位中的非數字字串(例如 ""、"12abc"、"abc")引發錯誤。v29.x 包含對這些錯誤情況的警告。
v22.0 中的編譯器更改
JSON 欄位名稱衝突
我們對欄位名稱衝突與 JSON 對映的處理方式進行了一些細微更改。在 proto3 中,我們部分放寬了限制,僅在欄位名稱產生區分大小寫的 JSON 對映(原始名稱的駝峰式)時才報錯。我們現在還檢查 json_name 選項,並對區分大小寫的衝突報錯。在 proto2 中,我們稍微收緊了限制,如果兩個 json_name 規範衝突,將報錯。如果隱式 JSON 對映(駝峰式)存在衝突,我們將在 proto2 中發出警告。
我們提供了一個臨時訊息/列舉選項來恢復舊行為。如果立即重新命名欄位不是您的選擇,請在特定訊息/列舉上設定 deprecated_legacy_json_field_conflicts 選項。此選項將在未來的版本中刪除,但會為您提供更多時間進行遷移。
v22.0 中 C++ API 的更改
4.22.0 對 C++ 執行時和 protoc 進行了破壞性更改,如8 月份宣佈。
Autotools 關閉
更改來源:PR #10132
在 v22.0 中,我們從 protobuf 編譯器和 C++ 執行時中刪除了所有 Autotools 支援。如果您正在使用 Autotools 構建其中任何一個,則必須遷移到 CMake 或 Bazel。我們有一些專用說明,用於使用 CMake 設定 protobuf。
Abseil 依賴
更改來源:PR #10416
從 v22.0 開始,我們明確依賴於 Abseil。這使我們能夠刪除大部分 stubs,這些 stubs 是從舊的內部程式碼分支出來的,後來成為 Abseil。存在許多細微的行為變化,但大多數對使用者應該是透明的。一些值得注意的更改包括
string_view -
absl::string_view已在我們的許多 API 中取代了const std::string&。這最常用於輸入引數,使用者應該不會注意到任何變化。在少數情況下(例如虛擬方法引數或返回型別),使用者可能需要進行顯式更改才能使用新的簽名。tables - 我們現在使用 Abseil 的
flat_hash_map、flat_hash_set、btree_map和btree_set,而不是 STL set/map。這些更高效,並支援異構查詢。這對於使用者來說應該是大部分不可見的,但可能會導致一些與表排序相關的細微行為變化。logging - Abseil 的日誌庫與我們的舊日誌程式碼非常相似,只是拼寫略有不同(例如,
ABSL_CHECK而不是GOOGLE_CHECK)。最大的區別在於它不支援異常,並且在FATAL斷言失敗時將始終崩潰。(以前我們有一個PROTOBUF_USE_EXCEPTIONS標誌來切換到異常。)由於這些只在遇到嚴重問題時發生,我們認為無條件崩潰是合適的響應。日誌更改來源:PR #11623
構建依賴項 - 新的構建依賴項總是會導致下游使用者的破壞。我們要求 Abseil LTS 20230125 或更高版本才能構建。
對於 Bazel 構建,當從您的
WORKSPACE執行protobuf_deps時,Abseil 將在固定的 LTS 版本上自動下載和構建。這應該是透明的,但如果您依賴於舊版本的 Abseil,則需要升級您的依賴項。對於 CMake 構建,我們將首先查詢由頂級 CMake 配置引入的現有 Abseil 安裝(參見說明)。否則,如果
protobuf_ABSL_PROVIDER設定為module(其預設值),我們將嘗試從我們的 git 子模組構建和連結 Abseil。如果protobuf_ABSL_PROVIDER設定為package,我們將查詢預安裝的 Abseil 系統版本。
GetCurrentTime 方法中的更改
在 Windows 上,GetCurrentTime() 是系統提供的宏名稱。在 v22.x 之前,Protobuf 錯誤地刪除了 GetCurrentTime() 的宏定義。這使得 Windows 開發人員在包含 後無法使用該宏。從 v22.x 開始,Protobuf 保留了宏定義。這可能會破壞依賴於先前行為的客戶程式碼,例如如果他們使用表示式 google::protobuf::util::TimeUtil::GetCurrentTime()。
要將您的應用程式遷移到新行為,請更改您的程式碼以執行以下操作之一
- 如果定義了
GetCurrent宏,則顯式取消定義GetCurrentTime宏 - 透過使用
(google::protobuf::util::TimeUtil::GetCurrentTime)()或類似表示式來阻止宏擴充套件
示例:取消定義宏
如果您不使用 Windows 宏,請使用此方法。
之前
#include <google/protobuf/util/time_util.h>
void F() {
auto time = google::protobuf::util::TimeUtil::GetCurrentTime();
}
之後
#include <google/protobuf/util/time_util.h>
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
void F() {
auto time = google::protobuf::util::TimeUtil::GetCurrentTime();
}
示例 2:阻止宏擴充套件
之前
#include <google/protobuf/util/time_util.h>
void F() {
auto time = google::protobuf::util::TimeUtil::GetCurrentTime();
}
之後
#include <google/protobuf/util/time_util.h>
void F() {
auto time = (google::protobuf::util::TimeUtil::GetCurrentTime)();
}
C++20 支援
更改來源:PR #10796
為了支援 C++20,我們已在 C++ 生成的 protobuf 程式碼中保留了新的 關鍵字。與其他保留關鍵字一樣,如果您將它們用於任何欄位、列舉或訊息,我們將新增下劃線字尾以使其成為有效的 C++。例如,concept 欄位將生成 concept_() getter。如果您有使用這些關鍵字的現有 proto,則需要更新引用它們的 C++ 程式碼以新增相應的下劃線。
最終類
更改來源:PR #11604
作為強化 Protobuf 庫中假設的更廣泛工作的一部分,我們已將一些從未打算繼承的類標記為 final。目前沒有已知的使用案例來繼承這些類,這樣做可能會導致問題。如果您的程式碼正在繼承這些類,則沒有緩解措施,但如果您認為您有使用繼承的一些有效理由,您可以提出問題。
容器靜態斷言
更改來源:PR #11550
作為強化 Protobuf 庫中假設的更廣泛工作的一部分,我們已將靜態斷言新增到 Map、RepeatedField 和 RepeatedPtrField 容器中。這些確保您僅使用這些容器和預期型別,如我們的文件中所述。如果您遇到這些靜態斷言,則應遷移您的程式碼以使用 Abseil 或 STL 容器。std::vector 是重複欄位容器的良好直接替換,而 std::unordered_map 或 absl::flat_hash_map 是 Map 的良好直接替換(前者提供類似的指標穩定性,而後者更高效)。
已清除元素棄用
關於“已清除欄位”的 RepeatedPtrField API 已被棄用,並將在以後的破壞性版本中完全刪除。這最初是作為在清除元素後重復使用元素的最佳化而新增的,但最終效果不佳。如果您正在使用此 API,您應該考慮遷移到 arenas 以獲得更好的記憶體重用。
UnsafeArena 棄用
更改來源:PR #10325
作為刪除 arena-unsafe API 的更廣泛工作的一部分,我們隱藏了 RepeatedField::UnsafeArenaSwap。這是我們目前刪除的唯一一個,但在以後的版本中,我們將繼續刪除它們並提供幫助程式來處理 arena 之間高效的借用模式。在單個 arena(或棧/堆)中,Swap 與 UnsafeArenaSwap 一樣高效。好處是如果您不小心在不同的 arena 之間呼叫它,它不會導致無效的記憶體操作。
對映對升級
更改來源:PR #11625
對於 v22.0,我們已開始清理 Map API,使其與 Abseil 和 STL 更加一致。值得注意的是,我們已將 MapPair 類替換為 std::pair 的別名。這對於大多數使用者應該是透明的,但如果您直接使用該類,您可能需要更新程式碼。
新 JSON 解析器
更改來源:PR #10729
我們在此版本中重寫了 C++ JSON 解析器。它應該主要是隱藏的更改,但不可避免地一些未記錄的怪癖可能會發生變化;請相應地進行測試。解析不符合 RFC-8219 JSON 的文件(例如缺少引號或使用非標準布林值的文件)已被棄用,並將在未來版本中刪除。欄位的序列化順序現在保證與欄位編號順序匹配,而之前則不那麼確定。
作為此次遷移的一部分,util/internal 下的所有檔案都已刪除。這些檔案用於舊解析器,從未打算在外部使用。
Arena::Init
更改來源:PR #10623
Arena 中的 Init 方法是沒有任何作用的程式碼,現在已刪除。如果您正在呼叫此方法,您可能打算直接使用一組 ArenaOptions 呼叫 Arena 建構函式。您應該刪除該呼叫或遷移到該建構函式。
ErrorCollector 遷移
更改來源:PR #11555
作為我們 Abseil 遷移的一部分,我們正在從 const std::string& 轉向 absl::string_view。對於我們的三個錯誤收集器類,如果不破壞現有程式碼,這是無法完成的。對於 v22.0,我們決定釋出兩種變體,並將方法從 AddError 和 AddWarning 重新命名為 RecordError 和 RecordWarning。舊簽名已被標記為棄用,並且效率會略低(由於字串複製),但否則仍然有效。您應該將這些遷移到新版本,因為 Add* 方法將在以後的破壞性版本中刪除。