remove duplicated code, correct test names, change config param

This commit is contained in:
Nick Wilcox
2020-08-05 18:58:26 +10:00
committed by Emilio Cobos Álvarez
parent 41b7866c14
commit 6fc7c77b0f
10 changed files with 148 additions and 127 deletions
+6 -5
View File
@@ -476,11 +476,6 @@ tab_width = 3
# default: "auto" # default: "auto"
documentation_style = "doxy" documentation_style = "doxy"
# An optional string that, if present, will decorate all pointers that are
# required to be non null. Nullability is inferred from the Rust type: `&T`,
# `&mut T` and `NonNull<T>` are all require a valid pointer value.
non_null_attribute = "_Nonnull"
@@ -942,6 +937,12 @@ default_features = true
# default: [] # default: []
features = ["cbindgen"] features = ["cbindgen"]
[ptr]
# An optional string to decorate all pointers that are
# required to be non null. Nullability is inferred from the Rust type: `&T`,
# `&mut T` and `NonNull<T>` all require a valid pointer value.
non_null_attribute = "_Nonnull"
``` ```
+37 -28
View File
@@ -14,7 +14,7 @@ use crate::bindgen::{Config, Language};
// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf // http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
enum CDeclarator { enum CDeclarator {
Ptr(bool, bool), Ptr { is_const: bool, is_nullable: bool },
Ref, Ref,
Array(String), Array(String),
Func(Vec<(Option<String>, CDecl)>, bool), Func(Vec<(Option<String>, CDecl)>, bool),
@@ -23,7 +23,7 @@ enum CDeclarator {
impl CDeclarator { impl CDeclarator {
fn is_ptr(&self) -> bool { fn is_ptr(&self) -> bool {
match self { match self {
CDeclarator::Ptr(..) | CDeclarator::Ref | CDeclarator::Func(..) => true, CDeclarator::Ptr { .. } | CDeclarator::Ref | CDeclarator::Func(..) => true,
_ => false, _ => false,
} }
} }
@@ -114,21 +114,25 @@ impl CDecl {
self.type_name = p.to_string(); self.type_name = p.to_string();
} }
Type::ConstPtr(ref t) => { Type::ConstPtr {
self.declarators.push(CDeclarator::Ptr(is_const, false)); ref ty,
self.build_type(t, true); is_nullable,
} => {
self.declarators.push(CDeclarator::Ptr {
is_const,
is_nullable: *is_nullable,
});
self.build_type(ty, true);
} }
Type::Ptr(ref t) => { Type::Ptr {
self.declarators.push(CDeclarator::Ptr(is_const, false)); ref ty,
self.build_type(t, false); is_nullable,
} } => {
Type::NonNullPtr(ref t) => { self.declarators.push(CDeclarator::Ptr {
self.declarators.push(CDeclarator::Ptr(is_const, true)); is_const,
self.build_type(t, false); is_nullable: *is_nullable,
} });
Type::ConstNonNullPtr(ref t) => { self.build_type(ty, false);
self.declarators.push(CDeclarator::Ptr(is_const, true));
self.build_type(t, true);
} }
Type::Ref(ref t) => { Type::Ref(ref t) => {
self.declarators.push(CDeclarator::Ref); self.declarators.push(CDeclarator::Ref);
@@ -148,7 +152,10 @@ impl CDecl {
.iter() .iter()
.map(|(ref name, ref ty)| (name.clone(), CDecl::from_type(ty))) .map(|(ref name, ref ty)| (name.clone(), CDecl::from_type(ty)))
.collect(); .collect();
self.declarators.push(CDeclarator::Ptr(false, false)); self.declarators.push(CDeclarator::Ptr {
is_const: false,
is_nullable: true,
});
self.declarators.push(CDeclarator::Func(args, false)); self.declarators.push(CDeclarator::Func(args, false));
self.build_type(ret, false); self.build_type(ret, false);
} }
@@ -186,17 +193,19 @@ impl CDecl {
let next_is_pointer = iter_rev.peek().map_or(false, |x| x.is_ptr()); let next_is_pointer = iter_rev.peek().map_or(false, |x| x.is_ptr());
match *declarator { match *declarator {
CDeclarator::Ptr(ref is_const, ref is_nonnull) => { CDeclarator::Ptr {
let non_null_attribute = if *is_nonnull { is_const,
config.non_null_attribute.as_ref() is_nullable,
} => {
if is_const {
out.write("*const ")
} else { } else {
None out.write("*")
}; }
match (non_null_attribute, is_const) { if !is_nullable {
(None, true) => out.write("*const "), if let Some(attr) = &config.pointer.non_null_attribute {
(None, false) => out.write("*"), write!(out, "{} ", attr);
(Some(attr), true) => write!(out, "*const {} ", attr), }
(Some(attr), false) => write!(out, "* {} ", attr),
} }
} }
CDeclarator::Ref => { CDeclarator::Ref => {
@@ -227,7 +236,7 @@ impl CDecl {
#[allow(clippy::while_let_on_iterator)] #[allow(clippy::while_let_on_iterator)]
while let Some(declarator) = iter.next() { while let Some(declarator) = iter.next() {
match *declarator { match *declarator {
CDeclarator::Ptr(..) => { CDeclarator::Ptr { .. } => {
last_was_pointer = true; last_was_pointer = true;
} }
CDeclarator::Ref => { CDeclarator::Ref => {
+22 -3
View File
@@ -692,6 +692,24 @@ impl ParseConfig {
} }
} }
/// Settings to apply to pointers
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "snake_case")]
#[serde(deny_unknown_fields)]
#[serde(default)]
pub struct PtrConfig {
/// Optional attribute to apply to pointers that are required to not be null
pub non_null_attribute: Option<String>,
}
impl Default for PtrConfig {
fn default() -> Self {
Self {
non_null_attribute: None,
}
}
}
/// A collection of settings to customize the generated bindings. /// A collection of settings to customize the generated bindings.
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
@@ -765,8 +783,9 @@ pub struct Config {
pub documentation: bool, pub documentation: bool,
/// How documentation comments should be styled. /// How documentation comments should be styled.
pub documentation_style: DocumentationStyle, pub documentation_style: DocumentationStyle,
/// Optional attribute to apply to pointers that are required to not be null /// Configuration options for pointers
pub non_null_attribute: Option<String>, #[serde(rename = "ptr")]
pub pointer: PtrConfig,
} }
impl Default for Config { impl Default for Config {
@@ -802,7 +821,7 @@ impl Default for Config {
defines: HashMap::new(), defines: HashMap::new(),
documentation: true, documentation: true,
documentation_style: DocumentationStyle::Auto, documentation_style: DocumentationStyle::Auto,
non_null_attribute: None, pointer: PtrConfig::default(),
} }
} }
} }
+2 -2
View File
@@ -494,7 +494,7 @@ impl Constant {
debug_assert!(config.structure.associated_constants_in_body); debug_assert!(config.structure.associated_constants_in_body);
debug_assert!(config.constant.allow_static_const); debug_assert!(config.constant.allow_static_const);
if let Type::ConstPtr(..) = self.ty { if let Type::ConstPtr { .. } = self.ty {
out.write("static "); out.write("static ");
} else { } else {
out.write("static const "); out.write("static const ");
@@ -579,7 +579,7 @@ impl Constant {
out.write(if in_body { "inline " } else { "static " }); out.write(if in_body { "inline " } else { "static " });
} }
if let Type::ConstPtr(..) = self.ty { if let Type::ConstPtr { .. } = self.ty {
// Nothing. // Nothing.
} else { } else {
out.write("const "); out.write("const ");
+8 -2
View File
@@ -305,8 +305,14 @@ fn gen_self_type(receiver: &syn::Receiver) -> Type {
let self_ty = Type::Path(GenericPath::self_path()); let self_ty = Type::Path(GenericPath::self_path());
match receiver.reference { match receiver.reference {
Some(_) => match receiver.mutability { Some(_) => match receiver.mutability {
Some(_) => Type::Ptr(Box::new(self_ty)), Some(_) => Type::Ptr {
None => Type::ConstPtr(Box::new(self_ty)), ty: Box::new(self_ty),
is_nullable: true,
},
None => Type::ConstPtr {
ty: Box::new(self_ty),
is_nullable: true,
},
}, },
None => self_ty, None => self_ty,
} }
+1 -1
View File
@@ -109,7 +109,7 @@ impl Item for Static {
impl Source for Static { impl Source for Static {
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) { fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
out.write("extern "); out.write("extern ");
if let Type::ConstPtr(..) = self.ty { if let Type::ConstPtr { .. } = self.ty {
} else if !self.mutable { } else if !self.mutable {
out.write("const "); out.write("const ");
} }
+65 -80
View File
@@ -209,10 +209,8 @@ impl ArrayLength {
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Type { pub enum Type {
ConstPtr(Box<Type>), ConstPtr { ty: Box<Type>, is_nullable: bool },
Ptr(Box<Type>), Ptr { ty: Box<Type>, is_nullable: bool },
ConstNonNullPtr(Box<Type>),
NonNullPtr(Box<Type>),
Ref(Box<Type>), Ref(Box<Type>),
MutRef(Box<Type>), MutRef(Box<Type>),
Path(GenericPath), Path(GenericPath),
@@ -237,8 +235,14 @@ impl Type {
}; };
match reference.mutability { match reference.mutability {
Some(_) => Type::NonNullPtr(Box::new(converted)), Some(_) => Type::Ptr {
None => Type::ConstNonNullPtr(Box::new(converted)), ty: Box::new(converted),
is_nullable: false,
},
None => Type::ConstPtr {
ty: Box::new(converted),
is_nullable: false,
},
} }
} }
syn::Type::Ptr(ref pointer) => { syn::Type::Ptr(ref pointer) => {
@@ -254,8 +258,14 @@ impl Type {
}; };
match pointer.mutability { match pointer.mutability {
Some(_) => Type::Ptr(Box::new(converted)), Some(_) => Type::Ptr {
None => Type::ConstPtr(Box::new(converted)), ty: Box::new(converted),
is_nullable: true,
},
None => Type::ConstPtr {
ty: Box::new(converted),
is_nullable: true,
},
} }
} }
syn::Type::Path(ref path) => { syn::Type::Path(ref path) => {
@@ -360,7 +370,7 @@ impl Type {
pub fn is_primitive_or_ptr_primitive(&self) -> bool { pub fn is_primitive_or_ptr_primitive(&self) -> bool {
match *self { match *self {
Type::Primitive(..) => true, Type::Primitive(..) => true,
Type::ConstPtr(ref x) => match x.as_ref() { Type::ConstPtr { ref ty, .. } => match ty.as_ref() {
Type::Primitive(..) => true, Type::Primitive(..) => true,
_ => false, _ => false,
}, },
@@ -370,10 +380,8 @@ impl Type {
pub fn is_repr_ptr(&self) -> bool { pub fn is_repr_ptr(&self) -> bool {
match *self { match *self {
Type::Ptr(..) => true, Type::Ptr { .. } => true,
Type::NonNullPtr(..) => true, Type::ConstPtr { .. } => true,
Type::ConstPtr(..) => true,
Type::ConstNonNullPtr(..) => true,
Type::FuncPtr(..) => true, Type::FuncPtr(..) => true,
_ => false, _ => false,
} }
@@ -381,10 +389,14 @@ impl Type {
pub fn make_nullable(&self) -> Option<Self> { pub fn make_nullable(&self) -> Option<Self> {
match self.clone() { match self.clone() {
Type::Ptr(x) => Some(Type::Ptr(x)), Type::Ptr { ty, .. } => Some(Type::Ptr {
Type::NonNullPtr(x) => Some(Type::Ptr(x)), ty,
Type::ConstPtr(x) => Some(Type::ConstPtr(x)), is_nullable: true,
Type::ConstNonNullPtr(x) => Some(Type::ConstPtr(x)), }),
Type::ConstPtr { ty, .. } => Some(Type::ConstPtr {
ty,
is_nullable: true,
}),
Type::FuncPtr(x, y) => Some(Type::FuncPtr(x, y)), Type::FuncPtr(x, y) => Some(Type::FuncPtr(x, y)),
_ => None, _ => None,
} }
@@ -406,7 +418,10 @@ impl Type {
match path.name() { match path.name() {
// FIXME(#223): This is not quite correct. // FIXME(#223): This is not quite correct.
"Option" if generic.is_repr_ptr() => generic.make_nullable(), "Option" if generic.is_repr_ptr() => generic.make_nullable(),
"NonNull" => Some(Type::NonNullPtr(Box::new(generic))), "NonNull" => Some(Type::Ptr {
ty: Box::new(generic),
is_nullable: false,
}),
"Cell" => Some(generic), "Cell" => Some(generic),
_ => None, _ => None,
} }
@@ -423,10 +438,8 @@ impl Type {
Type::Array(ref mut ty, ..) Type::Array(ref mut ty, ..)
| Type::MutRef(ref mut ty) | Type::MutRef(ref mut ty)
| Type::Ref(ref mut ty) | Type::Ref(ref mut ty)
| Type::Ptr(ref mut ty) | Type::Ptr { ref mut ty, .. }
| Type::NonNullPtr(ref mut ty) | Type::ConstPtr { ref mut ty, .. } => ty.replace_self_with(self_ty),
| Type::ConstNonNullPtr(ref mut ty)
| Type::ConstPtr(ref mut ty) => ty.replace_self_with(self_ty),
Type::Path(ref mut generic_path) => { Type::Path(ref mut generic_path) => {
generic_path.replace_self_with(self_ty); generic_path.replace_self_with(self_ty);
} }
@@ -444,10 +457,8 @@ impl Type {
let mut current = self; let mut current = self;
loop { loop {
match *current { match *current {
Type::ConstPtr(ref ty) => current = ty, Type::ConstPtr { ref ty, .. } => current = ty,
Type::Ptr(ref ty) => current = ty, Type::Ptr { ref ty, .. } => current = ty,
Type::NonNullPtr(ref ty) => current = ty,
Type::ConstNonNullPtr(ref ty) => current = ty,
Type::Ref(ref ty) => current = ty, Type::Ref(ref ty) => current = ty,
Type::MutRef(ref ty) => current = ty, Type::MutRef(ref ty) => current = ty,
Type::Path(ref generic) => { Type::Path(ref generic) => {
@@ -468,12 +479,20 @@ impl Type {
pub fn specialize(&self, mappings: &[(&Path, &Type)]) -> Type { pub fn specialize(&self, mappings: &[(&Path, &Type)]) -> Type {
match *self { match *self {
Type::ConstPtr(ref ty) => Type::ConstPtr(Box::new(ty.specialize(mappings))), Type::ConstPtr {
Type::Ptr(ref ty) => Type::Ptr(Box::new(ty.specialize(mappings))), ref ty,
Type::NonNullPtr(ref ty) => Type::NonNullPtr(Box::new(ty.specialize(mappings))), is_nullable,
Type::ConstNonNullPtr(ref ty) => { } => Type::ConstPtr {
Type::ConstNonNullPtr(Box::new(ty.specialize(mappings))) ty: Box::new(ty.specialize(mappings)),
} is_nullable,
},
Type::Ptr {
ref ty,
is_nullable,
} => Type::Ptr {
ty: Box::new(ty.specialize(mappings)),
is_nullable,
},
Type::Ref(ref ty) => Type::Ref(Box::new(ty.specialize(mappings))), Type::Ref(ref ty) => Type::Ref(Box::new(ty.specialize(mappings))),
Type::MutRef(ref ty) => Type::MutRef(Box::new(ty.specialize(mappings))), Type::MutRef(ref ty) => Type::MutRef(Box::new(ty.specialize(mappings))),
Type::Path(ref generic_path) => { Type::Path(ref generic_path) => {
@@ -514,16 +533,10 @@ impl Type {
out: &mut Dependencies, out: &mut Dependencies,
) { ) {
match *self { match *self {
Type::ConstPtr(ref ty) => { Type::ConstPtr { ref ty, .. } => {
ty.add_dependencies_ignoring_generics(generic_params, library, out); ty.add_dependencies_ignoring_generics(generic_params, library, out);
} }
Type::Ptr(ref ty) => { Type::Ptr { ref ty, .. } => {
ty.add_dependencies_ignoring_generics(generic_params, library, out);
}
Type::NonNullPtr(ref ty) => {
ty.add_dependencies_ignoring_generics(generic_params, library, out);
}
Type::ConstNonNullPtr(ref ty) => {
ty.add_dependencies_ignoring_generics(generic_params, library, out); ty.add_dependencies_ignoring_generics(generic_params, library, out);
} }
Type::Ref(ref ty) | Type::MutRef(ref ty) => { Type::Ref(ref ty) | Type::MutRef(ref ty) => {
@@ -574,16 +587,10 @@ impl Type {
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) { pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
match *self { match *self {
Type::ConstPtr(ref ty) => { Type::ConstPtr { ref ty, .. } => {
ty.add_monomorphs(library, out); ty.add_monomorphs(library, out);
} }
Type::Ptr(ref ty) => { Type::Ptr { ref ty, .. } => {
ty.add_monomorphs(library, out);
}
Type::NonNullPtr(ref ty) => {
ty.add_monomorphs(library, out);
}
Type::ConstNonNullPtr(ref ty) => {
ty.add_monomorphs(library, out); ty.add_monomorphs(library, out);
} }
Type::Ref(ref ty) | Type::MutRef(ref ty) => { Type::Ref(ref ty) | Type::MutRef(ref ty) => {
@@ -616,16 +623,10 @@ impl Type {
pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) { pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) {
match *self { match *self {
Type::ConstPtr(ref mut ty) => { Type::ConstPtr { ref mut ty, .. } => {
ty.rename_for_config(config, generic_params); ty.rename_for_config(config, generic_params);
} }
Type::Ptr(ref mut ty) => { Type::Ptr { ref mut ty, .. } => {
ty.rename_for_config(config, generic_params);
}
Type::NonNullPtr(ref mut ty) => {
ty.rename_for_config(config, generic_params);
}
Type::ConstNonNullPtr(ref mut ty) => {
ty.rename_for_config(config, generic_params); ty.rename_for_config(config, generic_params);
} }
Type::Ref(ref mut ty) | Type::MutRef(ref mut ty) => { Type::Ref(ref mut ty) | Type::MutRef(ref mut ty) => {
@@ -650,16 +651,10 @@ impl Type {
pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) { pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
match *self { match *self {
Type::ConstPtr(ref mut ty) => { Type::ConstPtr { ref mut ty, .. } => {
ty.resolve_declaration_types(resolver); ty.resolve_declaration_types(resolver);
} }
Type::Ptr(ref mut ty) => { Type::Ptr { ref mut ty, .. } => {
ty.resolve_declaration_types(resolver);
}
Type::NonNullPtr(ref mut ty) => {
ty.resolve_declaration_types(resolver);
}
Type::ConstNonNullPtr(ref mut ty) => {
ty.resolve_declaration_types(resolver); ty.resolve_declaration_types(resolver);
} }
Type::Ref(ref mut ty) | Type::MutRef(ref mut ty) => { Type::Ref(ref mut ty) | Type::MutRef(ref mut ty) => {
@@ -683,16 +678,10 @@ impl Type {
pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) { pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
match *self { match *self {
Type::ConstPtr(ref mut ty) => { Type::ConstPtr { ref mut ty, .. } => {
ty.mangle_paths(monomorphs); ty.mangle_paths(monomorphs);
} }
Type::Ptr(ref mut ty) => { Type::Ptr { ref mut ty, .. } => {
ty.mangle_paths(monomorphs);
}
Type::NonNullPtr(ref mut ty) => {
ty.mangle_paths(monomorphs);
}
Type::ConstNonNullPtr(ref mut ty) => {
ty.mangle_paths(monomorphs); ty.mangle_paths(monomorphs);
} }
Type::Ref(ref mut ty) | Type::MutRef(ref mut ty) => { Type::Ref(ref mut ty) | Type::MutRef(ref mut ty) => {
@@ -728,10 +717,8 @@ impl Type {
pub fn can_cmp_order(&self) -> bool { pub fn can_cmp_order(&self) -> bool {
match *self { match *self {
Type::ConstPtr(..) => true, Type::ConstPtr { .. } => true,
Type::Ptr(..) => true, Type::Ptr { .. } => true,
Type::NonNullPtr(..) => true,
Type::ConstNonNullPtr(..) => true,
Type::Ref(..) | Type::MutRef(..) => false, Type::Ref(..) | Type::MutRef(..) => false,
Type::Path(..) => true, Type::Path(..) => true,
Type::Primitive(ref p) => p.can_cmp_order(), Type::Primitive(ref p) => p.can_cmp_order(),
@@ -742,10 +729,8 @@ impl Type {
pub fn can_cmp_eq(&self) -> bool { pub fn can_cmp_eq(&self) -> bool {
match *self { match *self {
Type::ConstPtr(..) => true, Type::ConstPtr { .. } => true,
Type::Ptr(..) => true, Type::Ptr { .. } => true,
Type::NonNullPtr(..) => true,
Type::ConstNonNullPtr(..) => true,
Type::Ref(..) | Type::MutRef(..) => false, Type::Ref(..) | Type::MutRef(..) => false,
Type::Path(..) => true, Type::Path(..) => true,
Type::Primitive(ref p) => p.can_cmp_eq(), Type::Primitive(ref p) => p.can_cmp_eq(),
+2 -2
View File
@@ -58,11 +58,11 @@ impl<'a> Mangler<'a> {
Type::Primitive(ref primitive) => { Type::Primitive(ref primitive) => {
self.output.push_str(primitive.to_repr_rust()); self.output.push_str(primitive.to_repr_rust());
} }
Type::Ptr(ref ty) | Type::MutRef(ref ty) | Type::NonNullPtr(ref ty) => { Type::Ptr { ref ty, .. } | Type::MutRef(ref ty) => {
self.push(Separator::BeginMutPtr); self.push(Separator::BeginMutPtr);
self.append_mangled_type(&**ty, last); self.append_mangled_type(&**ty, last);
} }
Type::ConstPtr(ref ty) | Type::Ref(ref ty) | Type::ConstNonNullPtr(ref ty) => { Type::ConstPtr { ref ty, .. } | Type::Ref(ref ty) => {
self.push(Separator::BeginConstPtr); self.push(Separator::BeginConstPtr);
self.append_mangled_type(&**ty, last); self.append_mangled_type(&**ty, last);
} }
+4 -4
View File
@@ -37,16 +37,16 @@ pub extern "C" fn mutltiple_args(
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn mut_ref_arg(arg: &Pointers<u64>) {} pub extern "C" fn ref_arg(arg: &Pointers<u64>) {}
#[no_mangle] #[no_mangle]
pub extern "C" fn ref_arg(arg: &mut Pointers<u64>) {} pub extern "C" fn mut_ref_arg(arg: &mut Pointers<u64>) {}
#[no_mangle] #[no_mangle]
pub extern "C" fn optional_mut_ref_arg(arg: Option<&Pointers<u64>>) {} pub extern "C" fn optional_ref_arg(arg: Option<&Pointers<u64>>) {}
#[no_mangle] #[no_mangle]
pub extern "C" fn optional_ref_arg(arg: Option<&mut Pointers<u64>>) {} pub extern "C" fn optional_mut_ref_arg(arg: Option<&mut Pointers<u64>>) {}
#[no_mangle] #[no_mangle]
pub extern "C" fn nullable_const_ptr(arg: *const Pointers<u64>) {} pub extern "C" fn nullable_const_ptr(arg: *const Pointers<u64>) {}
+1
View File
@@ -6,4 +6,5 @@ header = """
#endif #endif
""" """
[ptr]
non_null_attribute = "CBINDGEN_NONNULL" non_null_attribute = "CBINDGEN_NONNULL"