C++: wrap generated DescriptorTable variable in extern "C" block

To implement extensions in Rust, we are going to need a symbol we can depend on
to force-link the C++ extension registration code. The `descriptor_table_xxxxx`
variable seems ideal for this: it already exists and is not public-facing, so
we can reuse it without increasing code size. This CL marks it `extern "C"` to
ensure that we can safely access it from Rust.

PiperOrigin-RevId: 696615312
pull/19258/head
Adam Cozzette 4 months ago committed by Copybara-Service
parent 6ceef1cdeb
commit 37b10b8f81
  1. 17
      csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs
  2. 5
      src/google/protobuf/compiler/cpp/file.cc
  3. 2
      src/google/protobuf/compiler/java/java_features.pb.h
  4. 2
      src/google/protobuf/compiler/plugin.pb.h
  5. 2
      src/google/protobuf/cpp_features.pb.h
  6. 2
      src/google/protobuf/descriptor.pb.h
  7. 23
      src/google/protobuf/descriptor_unittest.cc

@ -1,17 +0,0 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#endregion
namespace Google.Protobuf.Reflection;
internal sealed partial class FeatureSetDescriptor
{
// Canonical serialized form of the edition defaults, generated by embed_edition_defaults.
private const string DefaultsBase64 =
"ChMYhAciACoMCAEQAhgCIAMoATACChMY5wciACoMCAIQARgBIAIoATABChMY6AciDAgBEAEYASACKAEwASoAIOYHKOgH";
}

@ -1769,9 +1769,14 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations(io::Printer* p) {
)cc");
if (HasDescriptorMethods(file_, options_)) {
// The DescriptorTable needs to be extern "C" so that we can access it from
// Rust. We do not attempt to read the contents of the table in Rust, but
// just use the symbol to force-link the C++ generated code when necessary.
p->Emit(R"cc(
extern "C" {
$dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable
$desc_table$;
} // extern "C"
)cc");
}
}

@ -51,8 +51,10 @@ template <typename T>
struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto {
static const ::uint32_t offsets[];
};
extern "C" {
PROTOC_EXPORT extern const ::google::protobuf::internal::DescriptorTable
descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto;
} // extern "C"
namespace pb {
enum JavaFeatures_Utf8Validation : int;
PROTOC_EXPORT bool JavaFeatures_Utf8Validation_IsValid(int value);

@ -57,8 +57,10 @@ template <typename T>
struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
static const ::uint32_t offsets[];
};
extern "C" {
PROTOC_EXPORT extern const ::google::protobuf::internal::DescriptorTable
descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
} // extern "C"
namespace google {
namespace protobuf {
namespace compiler {

@ -51,8 +51,10 @@ template <typename T>
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fcpp_5ffeatures_2eproto {
static const ::uint32_t offsets[];
};
extern "C" {
PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable
descriptor_table_google_2fprotobuf_2fcpp_5ffeatures_2eproto;
} // extern "C"
namespace pb {
enum CppFeatures_StringType : int;
PROTOBUF_EXPORT bool CppFeatures_StringType_IsValid(int value);

@ -50,8 +50,10 @@ template <typename T>
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fdescriptor_2eproto {
static const ::uint32_t offsets[];
};
extern "C" {
PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable
descriptor_table_google_2fprotobuf_2fdescriptor_2eproto;
} // extern "C"
namespace google {
namespace protobuf {
enum Edition : int;

@ -44,6 +44,7 @@
#include "absl/log/scoped_mock_log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
@ -14104,6 +14105,28 @@ TEST_F(LazilyBuildDependenciesTest, Dependency) {
// ===================================================================
// This is effectively a static_assert ensuring that the generated
// descriptor_table variable is marked extern "C". The compiler will give us an
// error if the generated declaration does not match this one. We need this
// variable to be extern "C" so that we can refer to it from Rust.
//
// If this causes a linker error, it is likely because the name mangling
// changed. That can be fixed by updating to the new name from the generated
// code for unittest.proto.
#define DESCRIPTOR_TABLE_NAME \
descriptor_table_google_2fprotobuf_2funittest_2eproto
extern "C" {
extern const ::google::protobuf::internal::DescriptorTable DESCRIPTOR_TABLE_NAME;
}
TEST(DescriptorTableExternLinkageTest, DescriptorTableExternLinkageTest) {
// The goal of this assertion is just to verify that the descriptor_table
// variable declaration above still refers to a real thing.
EXPECT_TRUE(absl::EndsWith(DESCRIPTOR_TABLE_NAME.filename, "unittest.proto"));
}
} // namespace descriptor_unittest
} // namespace protobuf

Loading…
Cancel
Save