2

我正在制作一个包含以下代码的 Rust 库:

pub mod my_module{

    use std::os::raw::{c_int, c_double};
    use std::collections::HashMap;

    struct MyPrivateClass {
        my_parameter:c_int
    }

    (...)

    #[repr(C)]
    pub struct MyPublicClass {
        my_private_parameter:HashMap<String,MyPrivateClass>,
        pub my_public_parameter:c_int,
        pub my_other_public_parameter:c_double
    }

    (...)

}

我想使用 Objective-C 中的那个库。所以我使用cbindgen来生成一个 C 头文件。在我的 Objective-C 项目中,我只需要访问 MyPublicClass 的公共字段。但是生成的 C 标头包含我的公共结构的所有字段,包括私有字段。

这是生成的 C 头文件的样子:

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct HashMap_String__MyPrivateClass HashMap_String__MyPrivateClass;

typedef struct {
  HashMap_String__MyPrivateClass my_private_parameter;
  int my_public_parameter;
  double my_other_public_parameter;
} MyPublicClass;

在这种特殊情况下,HashMap 类型没有直接的 C 等效项,所以我不能使用这个 C 标头。

我只需要在我的 Rust 库中使用这个 HashMap。我不需要从 Objective-C 中使用它。

如何生成一个不暴露它的 C 头文件,而不破坏任何东西?

4

1 回答 1

0

我最终遵循了 mcarton 的回答并摆脱了将 MyPublicClass 暴露给我的 C 标头的需要。

因此,我依靠函数来访问参数,而不是直接将它们作为实例参数来访问。当从 Xcode 运行我的 Objective-C 项目时,它的缺点是无法从调试器检查 MyPublicClass 字段的值,但至少它可以按预期编译和工作。

我的锈代码:

// This struct is no longer exposed to C:
pub struct MyPublicClass {
    my_private_parameter:HashMap<String,MyPrivateClass>,
    pub my_public_parameter:c_int,
    pub my_other_public_parameter:c_double
}


impl MyPublicClass {
    pub fn new() -> Self {
        (…)
        MyPublicClass {
            my_private_parameter: … ,
            my_public_parameter: … ,
            my_other_public_parameter: … ,
        }
    }

    // Necessary to access my_public_parameter outside of Rust:
    pub fn get_my_public_parameter_value(&self) -> c_int {
        return self.my_public_parameter;
    }
}

// Exposed to C:
#[no_mangle]
pub unsafe extern fn my_public_class_new() -> *mut MyPublicClass {
    Box::into_raw(Box::new(MyPublicClass::new()))
}

// Exposed to C and necessary to access my_public_parameter outside of Rust:
#[no_mangle]
pub unsafe extern fn my_public_class_get_my_public_parameter_value(ptr: *mut MyPublicClass) -> c_int {
    let mpc = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };
    mpc.get_my_public_parameter_value()
}

C 标头:

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct MyPublicClass MyPublicClass;
MyPublicClass *my_public_class_new();
int my_public_class_get_my_public_parameter_value(MyPublicClass *ptr);
于 2019-12-09T20:59:54.120 回答