I am making a Rust library that contains the following code:
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
}
(...)
}
I want to use that library from Objective-C. So I’m using cbindgen to generate a C header. From my Objective-C project, I only need to access the public fields of MyPublicClass. But the C header generated contains all the fields of my public structs, including the private field.
This is what the generated C header looks like:
#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;
In this particular case, the HashMap type doesn’t have a straight C equivalent, so I can’t use this C header.
I only need to use this HashMap inside of my Rust library. I don’t need to use it from Objective-C.
How can I generate a C header that doesn’t expose it, without breaking anything?
I ended up following mcarton's answer and got rid of the need to expose MyPublicClass to my C header.
As a consequence, I rely on functions to access the parameters, instead of accessing them directly as instance parameters. This has the drawback of not being able to check the values of MyPublicClass fields from the debugger when running my Objective-C project from Xcode, but at least it compiles and works as expected.
My Rust code:
The C header: