112a9d9c8Sopenharmony_ci# Generating Bindings to C++ 212a9d9c8Sopenharmony_ci 312a9d9c8Sopenharmony_ci`bindgen` can handle some C++ features, but not all of them. To set 412a9d9c8Sopenharmony_ciexpectations: `bindgen` will give you the type definitions and FFI declarations 512a9d9c8Sopenharmony_ciyou need to build an API to the C++ library, but using those types in Rust will 612a9d9c8Sopenharmony_cibe nowhere near as nice as using them in C++. You will have to manually call 712a9d9c8Sopenharmony_ciconstructors, destructors, overloaded operators, etc yourself. 812a9d9c8Sopenharmony_ci 912a9d9c8Sopenharmony_ciWhen passing in header files, the file will automatically be treated as C++ if 1012a9d9c8Sopenharmony_ciit ends in `.hpp`. If it doesn't, adding `-x c++` clang args can be used to 1112a9d9c8Sopenharmony_ciforce C++ mode. You probably also want to use `-std=c++14` or similar clang args 1212a9d9c8Sopenharmony_cias well. 1312a9d9c8Sopenharmony_ci 1412a9d9c8Sopenharmony_ciYou pretty much **must** use [allowlisting](./allowlisting.md) when working 1512a9d9c8Sopenharmony_ciwith C++ to avoid pulling in all of the `std::.*` types, many of which `bindgen` 1612a9d9c8Sopenharmony_cicannot handle. Additionally, you may want to mark other types as 1712a9d9c8Sopenharmony_ci[opaque](./opaque.md) that `bindgen` stumbles on. It is recommended to mark 1812a9d9c8Sopenharmony_ciall of `std::.*` opaque, and to allowlist only precisely the functions and types 1912a9d9c8Sopenharmony_ciyou intend to use. 2012a9d9c8Sopenharmony_ci 2112a9d9c8Sopenharmony_ciYou should read up on the [FAQs](./faq.md) as well. 2212a9d9c8Sopenharmony_ci 2312a9d9c8Sopenharmony_ci## Supported Features 2412a9d9c8Sopenharmony_ci 2512a9d9c8Sopenharmony_ci* Inheritance (for the most part; there are 2612a9d9c8Sopenharmony_ci [some outstanding bugs](https://github.com/rust-lang/rust-bindgen/issues/380)) 2712a9d9c8Sopenharmony_ci 2812a9d9c8Sopenharmony_ci* Methods 2912a9d9c8Sopenharmony_ci 3012a9d9c8Sopenharmony_ci* Bindings to constructors and destructors (but they aren't implicitly or 3112a9d9c8Sopenharmony_ci automatically invoked) 3212a9d9c8Sopenharmony_ci 3312a9d9c8Sopenharmony_ci* Function and method overloading 3412a9d9c8Sopenharmony_ci 3512a9d9c8Sopenharmony_ci* Templates *without* specialization. You should be able to access individual 3612a9d9c8Sopenharmony_ci fields of the class or struct. 3712a9d9c8Sopenharmony_ci 3812a9d9c8Sopenharmony_ci## Unsupported Features 3912a9d9c8Sopenharmony_ci 4012a9d9c8Sopenharmony_ciWhen `bindgen` finds a type that is too difficult or impossible to translate 4112a9d9c8Sopenharmony_ciinto Rust, it will automatically treat it as an opaque blob of bytes. The 4212a9d9c8Sopenharmony_ciphilosophy is that 4312a9d9c8Sopenharmony_ci 4412a9d9c8Sopenharmony_ci1. we should always get layout, size, and alignment correct, and 4512a9d9c8Sopenharmony_ci 4612a9d9c8Sopenharmony_ci2. just because one type uses specialization, that shouldn't cause `bindgen` to 4712a9d9c8Sopenharmony_ci give up on everything else. 4812a9d9c8Sopenharmony_ci 4912a9d9c8Sopenharmony_ciWithout further ado, here are C++ features that `bindgen` does not support or 5012a9d9c8Sopenharmony_cicannot translate into Rust: 5112a9d9c8Sopenharmony_ci 5212a9d9c8Sopenharmony_ci* Inline functions and methods: see 5312a9d9c8Sopenharmony_ci["Why isn't `bindgen` generating bindings to inline functions?"](./faq.md#why-isnt-bindgen-generating-bindings-to-inline-functions) 5412a9d9c8Sopenharmony_ci 5512a9d9c8Sopenharmony_ci* Template functions, methods of template classes and structs. We don't know 5612a9d9c8Sopenharmony_ci which monomorphizations exist, and can't create new ones because we aren't a 5712a9d9c8Sopenharmony_ci C++ compiler. 5812a9d9c8Sopenharmony_ci 5912a9d9c8Sopenharmony_ci* Anything related to template specialization: 6012a9d9c8Sopenharmony_ci * Partial template specialization 6112a9d9c8Sopenharmony_ci * Traits templates 6212a9d9c8Sopenharmony_ci * Substitution Failure Is Not An Error (SFINAE) 6312a9d9c8Sopenharmony_ci 6412a9d9c8Sopenharmony_ci* Cross language inheritance, for example inheriting from a Rust struct in C++. 6512a9d9c8Sopenharmony_ci 6612a9d9c8Sopenharmony_ci* Automatically calling copy and/or move constructors or destructors. Supporting 6712a9d9c8Sopenharmony_ci this isn't possible with Rust's move semantics. 6812a9d9c8Sopenharmony_ci 6912a9d9c8Sopenharmony_ci* Exceptions: if a function called through a `bindgen`-generated interface 7012a9d9c8Sopenharmony_ci raises an exception that is not caught by the function itself, this will 7112a9d9c8Sopenharmony_ci generate undefined behaviour. See 7212a9d9c8Sopenharmony_ci [the tracking issue for exceptions](https://github.com/rust-lang/rust-bindgen/issues/1208) 7312a9d9c8Sopenharmony_ci for more details. 7412a9d9c8Sopenharmony_ci 7512a9d9c8Sopenharmony_ci* Many C++ specific aspects of calling conventions. For example in the Itanium abi types that are 7612a9d9c8Sopenharmony_ci "[non trivial for the purposes of calls](https://itanium-cxx-abi.github.io/cxx-abi/abi.html#non-trivial)" 7712a9d9c8Sopenharmony_ci should be passed by pointer, even if they are otherwise eligable to be passed in a register. 7812a9d9c8Sopenharmony_ci Similarly in both the Itanium and MSVC ABIs such types are returned by "hidden parameter", much like 7912a9d9c8Sopenharmony_ci large structs in C that would not fit into a register. This also applies to types with any base classes 8012a9d9c8Sopenharmony_ci in the MSVC ABI (see [x64 calling convention](https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#return-values)). 8112a9d9c8Sopenharmony_ci Because bindgen does not know about these rules generated interfaces using such types are currently invalid. 8212a9d9c8Sopenharmony_ci 8312a9d9c8Sopenharmony_ci## Constructor semantics 8412a9d9c8Sopenharmony_ci 8512a9d9c8Sopenharmony_ci`bindgen` will generate a wrapper for any class constructor declared in the 8612a9d9c8Sopenharmony_ciinput headers. For example, this headers file 8712a9d9c8Sopenharmony_ci 8812a9d9c8Sopenharmony_ci```c++ 8912a9d9c8Sopenharmony_ciclass MyClass { 9012a9d9c8Sopenharmony_ci public: 9112a9d9c8Sopenharmony_ci MyClass(); 9212a9d9c8Sopenharmony_ci void method(); 9312a9d9c8Sopenharmony_ci}; 9412a9d9c8Sopenharmony_ci``` 9512a9d9c8Sopenharmony_ci 9612a9d9c8Sopenharmony_ciWill produce the following code: 9712a9d9c8Sopenharmony_ci```rust,ignore 9812a9d9c8Sopenharmony_ci#[repr(C)] 9912a9d9c8Sopenharmony_ci#[derive(Debug, Copy, Clone)] 10012a9d9c8Sopenharmony_cipub struct MyClass { 10112a9d9c8Sopenharmony_ci pub _address: u8, 10212a9d9c8Sopenharmony_ci} 10312a9d9c8Sopenharmony_ciextern "C" { 10412a9d9c8Sopenharmony_ci #[link_name = "\u{1}_ZN7MyClass6methodEv"] 10512a9d9c8Sopenharmony_ci pub fn MyClass_method(this: *mut MyClass); 10612a9d9c8Sopenharmony_ci} 10712a9d9c8Sopenharmony_ciextern "C" { 10812a9d9c8Sopenharmony_ci #[link_name = "\u{1}_ZN7MyClassC1Ev"] 10912a9d9c8Sopenharmony_ci pub fn MyClass_MyClass(this: *mut MyClass); 11012a9d9c8Sopenharmony_ci} 11112a9d9c8Sopenharmony_ciimpl MyClass { 11212a9d9c8Sopenharmony_ci #[inline] 11312a9d9c8Sopenharmony_ci pub unsafe fn method(&mut self) { 11412a9d9c8Sopenharmony_ci MyClass_method(self) 11512a9d9c8Sopenharmony_ci } 11612a9d9c8Sopenharmony_ci #[inline] 11712a9d9c8Sopenharmony_ci pub unsafe fn new() -> Self { 11812a9d9c8Sopenharmony_ci let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); 11912a9d9c8Sopenharmony_ci MyClass_MyClass(__bindgen_tmp.as_mut_ptr()); 12012a9d9c8Sopenharmony_ci __bindgen_tmp.assume_init() 12112a9d9c8Sopenharmony_ci } 12212a9d9c8Sopenharmony_ci} 12312a9d9c8Sopenharmony_ci``` 12412a9d9c8Sopenharmony_ciThis `MyClass::new` Rust method can be used as a substitute for the `MyClass` 12512a9d9c8Sopenharmony_ciC++ constructor. However, the address of the value from inside the method will 12612a9d9c8Sopenharmony_cibe different than from the outside. This is because the `__bindgen_tmp` value 12712a9d9c8Sopenharmony_ciis moved when the `MyClass::new` method returns. 12812a9d9c8Sopenharmony_ci 12912a9d9c8Sopenharmony_ciIn contrast, the C++ constructor will not move the value, meaning that the 13012a9d9c8Sopenharmony_ciaddress of the value will be the same inside and outside the constructor. 13112a9d9c8Sopenharmony_ciIf the original C++ relies on this semantic difference somehow, you should use the 13212a9d9c8Sopenharmony_ci`MyClass_MyClass` binding directly instead of the `MyClass::new` method. 13312a9d9c8Sopenharmony_ci 13412a9d9c8Sopenharmony_ciIn other words, the Rust equivalent for the following C++ code 13512a9d9c8Sopenharmony_ci 13612a9d9c8Sopenharmony_ci```c++ 13712a9d9c8Sopenharmony_ciMyClass instance = MyClass(); 13812a9d9c8Sopenharmony_ciinstance.method(); 13912a9d9c8Sopenharmony_ci``` 14012a9d9c8Sopenharmony_ci 14112a9d9c8Sopenharmony_ciis not this 14212a9d9c8Sopenharmony_ci 14312a9d9c8Sopenharmony_ci```rust,ignore 14412a9d9c8Sopenharmony_cilet instance = MyClass::new(); 14512a9d9c8Sopenharmony_ciinstance.method(); 14612a9d9c8Sopenharmony_ci``` 14712a9d9c8Sopenharmony_ci 14812a9d9c8Sopenharmony_cibut this 14912a9d9c8Sopenharmony_ci 15012a9d9c8Sopenharmony_ci```rust,ignore 15112a9d9c8Sopenharmony_cilet instance = std::mem::MaybeUninit::<MyClass>::uninit(); 15212a9d9c8Sopenharmony_ciMyClass_MyClass(instance.as_mut_ptr()); 15312a9d9c8Sopenharmony_ciinstance.assume_init_mut().method(); 15412a9d9c8Sopenharmony_ci``` 15512a9d9c8Sopenharmony_ci 15612a9d9c8Sopenharmony_ciYou can easily verify this fact if you provide a implementation for `MyClass` 15712a9d9c8Sopenharmony_ciand `method` that prints the the `this` pointer address. However, you can 15812a9d9c8Sopenharmony_ciignore this fact if you know that the original C++ code does not rely on the 15912a9d9c8Sopenharmony_ciinstance address in its internal logic. 160