1# Generating Bindings to C++ 2 3`bindgen` can handle some C++ features, but not all of them. To set 4expectations: `bindgen` will give you the type definitions and FFI declarations 5you need to build an API to the C++ library, but using those types in Rust will 6be nowhere near as nice as using them in C++. You will have to manually call 7constructors, destructors, overloaded operators, etc yourself. 8 9When passing in header files, the file will automatically be treated as C++ if 10it ends in `.hpp`. If it doesn't, adding `-x c++` clang args can be used to 11force C++ mode. You probably also want to use `-std=c++14` or similar clang args 12as well. 13 14You pretty much **must** use [allowlisting](./allowlisting.md) when working 15with C++ to avoid pulling in all of the `std::.*` types, many of which `bindgen` 16cannot handle. Additionally, you may want to mark other types as 17[opaque](./opaque.md) that `bindgen` stumbles on. It is recommended to mark 18all of `std::.*` opaque, and to allowlist only precisely the functions and types 19you intend to use. 20 21You should read up on the [FAQs](./faq.md) as well. 22 23## Supported Features 24 25* Inheritance (for the most part; there are 26 [some outstanding bugs](https://github.com/rust-lang/rust-bindgen/issues/380)) 27 28* Methods 29 30* Bindings to constructors and destructors (but they aren't implicitly or 31 automatically invoked) 32 33* Function and method overloading 34 35* Templates *without* specialization. You should be able to access individual 36 fields of the class or struct. 37 38## Unsupported Features 39 40When `bindgen` finds a type that is too difficult or impossible to translate 41into Rust, it will automatically treat it as an opaque blob of bytes. The 42philosophy is that 43 441. we should always get layout, size, and alignment correct, and 45 462. just because one type uses specialization, that shouldn't cause `bindgen` to 47 give up on everything else. 48 49Without further ado, here are C++ features that `bindgen` does not support or 50cannot translate into Rust: 51 52* Inline functions and methods: see 53["Why isn't `bindgen` generating bindings to inline functions?"](./faq.md#why-isnt-bindgen-generating-bindings-to-inline-functions) 54 55* Template functions, methods of template classes and structs. We don't know 56 which monomorphizations exist, and can't create new ones because we aren't a 57 C++ compiler. 58 59* Anything related to template specialization: 60 * Partial template specialization 61 * Traits templates 62 * Substitution Failure Is Not An Error (SFINAE) 63 64* Cross language inheritance, for example inheriting from a Rust struct in C++. 65 66* Automatically calling copy and/or move constructors or destructors. Supporting 67 this isn't possible with Rust's move semantics. 68 69* Exceptions: if a function called through a `bindgen`-generated interface 70 raises an exception that is not caught by the function itself, this will 71 generate undefined behaviour. See 72 [the tracking issue for exceptions](https://github.com/rust-lang/rust-bindgen/issues/1208) 73 for more details. 74 75* Many C++ specific aspects of calling conventions. For example in the Itanium abi types that are 76 "[non trivial for the purposes of calls](https://itanium-cxx-abi.github.io/cxx-abi/abi.html#non-trivial)" 77 should be passed by pointer, even if they are otherwise eligable to be passed in a register. 78 Similarly in both the Itanium and MSVC ABIs such types are returned by "hidden parameter", much like 79 large structs in C that would not fit into a register. This also applies to types with any base classes 80 in the MSVC ABI (see [x64 calling convention](https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#return-values)). 81 Because bindgen does not know about these rules generated interfaces using such types are currently invalid. 82 83## Constructor semantics 84 85`bindgen` will generate a wrapper for any class constructor declared in the 86input headers. For example, this headers file 87 88```c++ 89class MyClass { 90 public: 91 MyClass(); 92 void method(); 93}; 94``` 95 96Will produce the following code: 97```rust,ignore 98#[repr(C)] 99#[derive(Debug, Copy, Clone)] 100pub struct MyClass { 101 pub _address: u8, 102} 103extern "C" { 104 #[link_name = "\u{1}_ZN7MyClass6methodEv"] 105 pub fn MyClass_method(this: *mut MyClass); 106} 107extern "C" { 108 #[link_name = "\u{1}_ZN7MyClassC1Ev"] 109 pub fn MyClass_MyClass(this: *mut MyClass); 110} 111impl MyClass { 112 #[inline] 113 pub unsafe fn method(&mut self) { 114 MyClass_method(self) 115 } 116 #[inline] 117 pub unsafe fn new() -> Self { 118 let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); 119 MyClass_MyClass(__bindgen_tmp.as_mut_ptr()); 120 __bindgen_tmp.assume_init() 121 } 122} 123``` 124This `MyClass::new` Rust method can be used as a substitute for the `MyClass` 125C++ constructor. However, the address of the value from inside the method will 126be different than from the outside. This is because the `__bindgen_tmp` value 127is moved when the `MyClass::new` method returns. 128 129In contrast, the C++ constructor will not move the value, meaning that the 130address of the value will be the same inside and outside the constructor. 131If the original C++ relies on this semantic difference somehow, you should use the 132`MyClass_MyClass` binding directly instead of the `MyClass::new` method. 133 134In other words, the Rust equivalent for the following C++ code 135 136```c++ 137MyClass instance = MyClass(); 138instance.method(); 139``` 140 141is not this 142 143```rust,ignore 144let instance = MyClass::new(); 145instance.method(); 146``` 147 148but this 149 150```rust,ignore 151let instance = std::mem::MaybeUninit::<MyClass>::uninit(); 152MyClass_MyClass(instance.as_mut_ptr()); 153instance.assume_init_mut().method(); 154``` 155 156You can easily verify this fact if you provide a implementation for `MyClass` 157and `method` that prints the the `this` pointer address. However, you can 158ignore this fact if you know that the original C++ code does not rely on the 159instance address in its internal logic. 160