1

我正在为定义标准常量默认值列表的 C 库创建 Rust 绑定:

// C

typedef struct RMW_PUBLIC_TYPE rmw_qos_profile_t
{
  size_t depth;
  enum rmw_qos_reliability_policy_t reliability;
  // ...
} rmw_qos_profile_t;

enum RMW_PUBLIC_TYPE rmw_qos_reliability_policy_t
{
  RMW_QOS_POLICY_RELIABILITY_RELIABLE,
  RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT,
  // ...
};

// Global value that needs wrapping
static const rmw_qos_profile_t rmw_qos_profile_sensor_data =
{
  5,
  RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT,
  // ...
};

使用 Bindgen,static生成 Rust 变量:

// Rust

extern "C" {
    #[link_name = "\u{1}rmw_qos_profile_sensor_data"]
    pub static rmw_qos_profile_sensor_data: rmw_qos_profile_t;
}

但是static全局变量在 Rust 中使用起来非常不方便,必须将每个访问都封装在一个unsafe {}块中。特别是当您不需要可变性时。

我已经用 Rust 包装了结构和枚举:

// Rust

pub enum QoSReliabilityPolicy {
    Reliable = 0,
    BestEffort = 1,
}

impl From<rmw_qos_reliability_policy_t> for QoSReliabilityPolicy {
    fn from(raw: rmw_qos_reliability_policy_t) -> Self {
        match raw {
            rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_RELIABLE => QoSReliabilityPolicy::Reliable,
            rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT => QoSReliabilityPolicy::BestEffort,
        }
    }
}

pub struct QoSProfile {
    pub depth: usize,
    pub reliability: QoSReliabilityPolicy,
    // ...
}

impl From<rmw_qos_profile_t> for QoSProfile {
    fn from(qos_profile: rmw_qos_profile_t) -> Self {
        QoSProfile {
            depth: qos_profile.depth,
            reliability: qos_profile.reliability.into(),
            // ...
        }
    }
}

impl From<rmw_qos_profile_t> for QoSProfile {
    fn from(qos_profile: rmw_qos_profile_t) -> Self {
        QoSProfile {
            depth: qos_profile.depth,
            reliability: qos_profile.reliability.into(),
            // ...
        }
    }
}

现在,我正在寻找一种解决方案来rmw_qos_profile_sensor_data向我的 Rust 用户公开相同的预定义配置文件,例如 ,而无需在 Rust 中手动复制 C 值。

目前我正在用 Rust 复制 C 代码:

// Rust

// Works but unsatisfying
pub const QOS_PROFILE_SENSOR_DATA: QoSProfile = QoSProfile {
    depth: 5,
    reliability: QoSReliabilityPolicy::BestEffort,
    // ...
};

但这并不令人满意。当上游 C 库更新这些值时,用户会遇到不一致的行为和错误。

方便地包装这些全局常量的可能解决方案是什么?

理想的解决方案是:

  • 上游 C 库更改时自动更新值
  • 公开 globalconst以便编译器可以内联这些值
  • 如果不可能,公开全局不可变变量
  • 如果仍然不可能,至少不需要unsafe

我一直面临的问题是,由于static constC 结构存储在内存中,它们不能const轻易翻译成 a,这可能就是 Bindgen 使用static关键字翻译它的原因。

因此,我可以想象但不知道如何执行的可能性是:

  • 对 C 代码进行更智能的解析以生成 Rust 代码?
  • 使用某种形式的宏
  • 从前奏中的 C lib 的静态内存初始化?
  • 显式地从 C lib 的静态内存初始化?
  • 其他解决方案?
4

0 回答 0