【CXX】1 CXX主要概念概览

本文描述了CXX(一个用于在Rust和C++之间进行桥接的库)中的关键概念,特别是FFI(外部函数接口)边界所涉及的三种主要类型:共享结构体、不透明类型和函数。

一、示例代码

#[cxx::bridge]
mod ffi {
    // 任何共享结构,其字段对两种语言都是可见的。
    struct BlobMetadata {
        size: usize,
        tags: Vec<String>,
    }

    extern "Rust" {
        // 两种语言都可以传递零个或多个不透明类型,但只有Rust可以看到这些字段。
        type MultiBuf;

        // 在Rust中实现的函数。
        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
    }

    unsafe extern "C++" {
        // 一个或多个C++匹配的头文件,其中包含封闭的extern "C++"块。我们的代码生成器不会读取它,但它会被#included并用于静态断言中,以确保我们对FFI边界的理解是准确的。
        //在extern "C++"部分,我们列出了C++为事实来源的类型和函数,以及声明这些API的头文件。将来这部分可能会从头文件中生成,但目前我们需要写出签名;静态断言会验证它们的准确性。
        include!("demo/include/blobstore.h");

        // 两种语言都可以传递零个或多个不透明类型,但只有C++可以看到这些字段。
        type BlobstoreClient;

        // 用C++实现的函数。
        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
        fn put(&self, parts: &mut MultiBuf) -> u64;
        fn tag(&self, blobid: u64, tag: &str);
        fn metadata(&self, blobid: u64) -> BlobMetadata;
    }
}

二、FFI边界所涉及的三种主要类型

  1. 共享结构体(Shared Structs)
  • 定义:共享结构体是那些在Rust和C++中字段都可见的数据结构。
  • 用途:当两种语言都需要访问结构体的字段时,使用共享结构体。
  • 实现:通常在Rust中定义这些结构体,并通过cxx::bridge宏将其暴露给C++。这允许两种语言以一致的方式访问和操作这些数据结构。
  • 示例:在示例中,BlobMetadata是一个共享结构体,它包含了size和tags字段,这些字段在Rust和C++中都是可见的。
  1. 不透明类型(Opaque Types)
  • 定义:不透明类型的字段对另一种语言是保密的。
  • 用途:当一种语言需要引用另一种语言中定义的复杂类型,但不希望暴露其内部实现时,使用不透明类型。
  • 实现:这些类型通常通过引用(如Rust的&、Box或C++的unique_ptr)在FFI中传递。
  • 示例:在示例中,MultiBuf和BlobstoreClient都是不透明类型。在Rust中,MultiBuf的字段对C++是保密的,同样,BlobstoreClient的字段对Rust也是保密的。
  1. 函数(Functions)
  • 定义:函数可以在任意一种语言中实现,然后从另一种语言中调用。
  • 用途:函数是实现Rust和C++之间交互的核心机制。
  • 实现:在cxx::bridge宏中,通过extern "Rust"和extern "C++"块分别列出Rust和C++中实现的函数。
  • 示例:在示例中,next_chunk函数在Rust中实现,并从C++中调用;而new_blobstore_client、put、tag和metadata函数在C++中实现,并从Rust中调用。

三、CXX库的设计特点

  • 有限制性和有观点的:CXX库不是设计为处理所有可能的Rust和C++签名,而是专注于提供一套能够做出安全保证的功能。
  • 需要练习:由于CXX桥接不会以所有可能习惯的方式工作,因此有效地使用它可能需要一些实践和学习。

四、使用注意事项

  • 静态断言:在extern "C++"部分,CXX自动使用静态断言来验证签名的准确性,这有助于确保FFI边界的理解是一致的。
  • 父模块引用:在extern "Rust"部分列出的类型和函数隐含地引用了CXX的父模块。这通常通过相关的use语句来实现。

五、总结

CXX库为Rust和C++之间的桥接提供了一个强大的框架,通过共享结构体、不透明类型和函数等机制,允许两种语言之间进行高效、安全的交互。理解这些关键概念是使用CXX库的基础。

你可能感兴趣的:(CXX,rust,CXX,c++)