Skip to content

Commit 37b10b8

Browse files
acozzettecopybara-github
authored andcommitted
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
1 parent 6ceef1c commit 37b10b8

File tree

7 files changed

+36
-17
lines changed

7 files changed

+36
-17
lines changed

csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs

-17
This file was deleted.

src/google/protobuf/compiler/cpp/file.cc

+5
Original file line numberDiff line numberDiff line change
@@ -1769,9 +1769,14 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations(io::Printer* p) {
17691769
)cc");
17701770

17711771
if (HasDescriptorMethods(file_, options_)) {
1772+
// The DescriptorTable needs to be extern "C" so that we can access it from
1773+
// Rust. We do not attempt to read the contents of the table in Rust, but
1774+
// just use the symbol to force-link the C++ generated code when necessary.
17721775
p->Emit(R"cc(
1776+
extern "C" {
17731777
$dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable
17741778
$desc_table$;
1779+
} // extern "C"
17751780
)cc");
17761781
}
17771782
}

src/google/protobuf/compiler/java/java_features.pb.h

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/google/protobuf/compiler/plugin.pb.h

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/google/protobuf/cpp_features.pb.h

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/google/protobuf/descriptor.pb.h

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/google/protobuf/descriptor_unittest.cc

+23
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "absl/log/scoped_mock_log.h"
4545
#include "absl/status/status.h"
4646
#include "absl/status/statusor.h"
47+
#include "absl/strings/match.h"
4748
#include "absl/strings/numbers.h"
4849
#include "absl/strings/str_cat.h"
4950
#include "absl/strings/str_format.h"
@@ -14104,6 +14105,28 @@ TEST_F(LazilyBuildDependenciesTest, Dependency) {
1410414105

1410514106
// ===================================================================
1410614107

14108+
// This is effectively a static_assert ensuring that the generated
14109+
// descriptor_table variable is marked extern "C". The compiler will give us an
14110+
// error if the generated declaration does not match this one. We need this
14111+
// variable to be extern "C" so that we can refer to it from Rust.
14112+
//
14113+
// If this causes a linker error, it is likely because the name mangling
14114+
// changed. That can be fixed by updating to the new name from the generated
14115+
// code for unittest.proto.
14116+
14117+
#define DESCRIPTOR_TABLE_NAME \
14118+
descriptor_table_google_2fprotobuf_2funittest_2eproto
14119+
14120+
extern "C" {
14121+
extern const ::google::protobuf::internal::DescriptorTable DESCRIPTOR_TABLE_NAME;
14122+
}
14123+
14124+
TEST(DescriptorTableExternLinkageTest, DescriptorTableExternLinkageTest) {
14125+
// The goal of this assertion is just to verify that the descriptor_table
14126+
// variable declaration above still refers to a real thing.
14127+
EXPECT_TRUE(absl::EndsWith(DESCRIPTOR_TABLE_NAME.filename, "unittest.proto"));
14128+
}
14129+
1410714130

1410814131
} // namespace descriptor_unittest
1410914132
} // namespace protobuf

0 commit comments

Comments
 (0)