Скрыть закрытые поля библиотеки Rust при генерации ее заголовка C
Я делаю библиотеку 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.
Мне нужно использовать этот HashMap только внутри моей библиотеки Rust. Мне не нужно использовать его из Objective-C.
Как я могу создать заголовок C, который не раскрывает его, ничего не нарушая?
1 ответ
В итоге я последовал за ответом Маккартона и избавился от необходимости предоставлять MyPublicClass для моего заголовка C.
Как следствие, я полагаюсь на функции для доступа к параметрам, вместо того, чтобы обращаться к ним напрямую как к параметрам экземпляра. У этого есть недостаток, заключающийся в невозможности проверки значений полей MyPublicClass из отладчика при запуске моего проекта Objective-C из Xcode, но, по крайней мере, он компилируется и работает должным образом.
Мой код на Rust:
// 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);