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