In this CL I'd like to call existing C++ Protobuf API from the V0 Rust API. Since parts of the C++ API are defined inline and using (obviously) C++ name mangling, we need to create a "thunks.cc" file that: 1) Generates code for C++ API function we use from Rust 2) Exposes these functions without any name mangling (meaning using `extern "C"`) In this CL we add Bazel logic to generate "thunks" file, compile it, and propagate its object to linking. We also add logic to protoc to generate this "thunks" file. The protoc logic is rather rudimentary still. I hope to focus on protoc code quality in my followup work on V0 Rust API using C++ kernel. PiperOrigin-RevId: 523479839pull/12367/head
parent
c23f226585
commit
5814f6c977
14 changed files with 544 additions and 75 deletions
@ -0,0 +1,80 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2023 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file contains support code for generated C++ thunks.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_CPP_H__ |
||||
#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_CPP_H__ |
||||
|
||||
#include <cstddef> |
||||
#include <iostream> |
||||
#include <string> |
||||
|
||||
#include "google/protobuf/message.h" |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace rust_internal { |
||||
|
||||
// Represents serialized Protobuf wire format data.
|
||||
//
|
||||
// Only to be used to transfer serialized data from C++ to Rust under these
|
||||
// assumptions:
|
||||
// * Rust and C++ versions of this struct are ABI compatible.
|
||||
// * Rust version owns and frees its data.
|
||||
// * The data were allocated using the Rust allocator.
|
||||
//
|
||||
extern "C" struct SerializedData { |
||||
/// Owns the memory.
|
||||
const char* data; |
||||
size_t len; |
||||
|
||||
SerializedData(const char* data, size_t len) : data(data), len(len) {} |
||||
}; |
||||
|
||||
// Allocates memory using the current Rust global allocator.
|
||||
//
|
||||
// This function is defined in `rust_alloc_for_cpp_api.rs`.
|
||||
extern "C" void* __pb_rust_alloc(size_t size, size_t align); |
||||
|
||||
inline SerializedData SerializeMsg(const google::protobuf::Message* msg) { |
||||
size_t len = msg->ByteSizeLong(); |
||||
void* bytes = __pb_rust_alloc(len, alignof(char)); |
||||
if (!msg->SerializeToArray(bytes, static_cast<int>(len))) { |
||||
ABSL_LOG(FATAL) << "Couldn't serialize the message."; |
||||
} |
||||
return SerializedData(static_cast<char*>(bytes), len); |
||||
} |
||||
|
||||
} // namespace rust_internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_CPP_H__
|
@ -0,0 +1,37 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2023 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use std::alloc::{alloc, Layout}; |
||||
|
||||
#[no_mangle] |
||||
extern "C" fn __pb_rust_alloc(size: usize, align: usize) -> *mut u8 { |
||||
let layout = Layout::from_size_align(size, align).unwrap(); |
||||
unsafe { alloc(layout) } |
||||
} |
@ -0,0 +1,30 @@ |
||||
# This package contains tests exercising C++/Rust interop in the cpp kernel. |
||||
|
||||
load("@rules_rust//rust:defs.bzl", "rust_test") |
||||
|
||||
cc_library( |
||||
name = "test_utils", |
||||
srcs = ["test_utils.cc"], |
||||
deps = [ |
||||
"//rust/cpp_kernel:cpp_api", |
||||
"//rust/test:unittest_cc_proto", |
||||
], |
||||
) |
||||
|
||||
rust_test( |
||||
name = "interop_test", |
||||
srcs = ["main.rs"], |
||||
tags = [ |
||||
# TODO(b/270274576): Enable testing on arm once we have a Rust Arm toolchain. |
||||
"not_build:arm", |
||||
# TODO(b/243126140): Enable tsan once we support sanitizers with Rust. |
||||
"notsan", |
||||
# TODO(b/243126140): Enable msan once we support sanitizers with Rust. |
||||
"nomsan", |
||||
], |
||||
deps = [ |
||||
":test_utils", |
||||
"//rust:protobuf_cpp", |
||||
"//rust/test:unittest_cc_rust_proto", |
||||
], |
||||
) |
@ -0,0 +1,47 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2023 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use std::ptr::NonNull; |
||||
|
||||
#[test] |
||||
fn mutate_message_in_cpp() { |
||||
let mut msg = unittest_proto::TestAllTypes::new(); |
||||
unsafe { MutateInt32Field(msg.__unstable_cpp_repr_grant_permission_to_break()) }; |
||||
let serialized_msg_from_cpp = |
||||
unsafe { Serialize(msg.__unstable_cpp_repr_grant_permission_to_break()) }; |
||||
assert_eq!(*msg.serialize(), *serialized_msg_from_cpp); |
||||
} |
||||
|
||||
// Helper functions invoking C++ Protobuf APIs directly in C++. Defined in
|
||||
// `//third_party/protobuf/rust/test/cpp/interop:test_utils`.
|
||||
extern "C" { |
||||
fn MutateInt32Field(msg: NonNull<u8>); |
||||
fn Serialize(msg: NonNull<u8>) -> protobuf_cpp::SerializedData; |
||||
} |
@ -0,0 +1,43 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2023 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <iostream> |
||||
|
||||
#include "google/protobuf/rust/cpp_kernel/cpp_api.h" |
||||
#include "google/protobuf/unittest.pb.h" |
||||
|
||||
extern "C" void MutateInt32Field(protobuf_unittest::TestAllTypes* msg) { |
||||
msg->set_optional_int32(42); |
||||
} |
||||
|
||||
extern "C" google::protobuf::rust_internal::SerializedData Serialize( |
||||
const protobuf_unittest::TestAllTypes* msg) { |
||||
return google::protobuf::rust_internal::SerializeMsg(msg); |
||||
} |
Loading…
Reference in new issue