@@ -79,3 +79,81 @@ cannot translate into Rust:
7979 large structs in C that would not fit into a register. This also applies to types with any base classes
8080 in the MSVC ABI (see [ x64 calling convention] ( https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#return-values ) ).
8181 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
86+ input headers. For example, this headers file
87+
88+ ``` c++
89+ class MyClass {
90+ public:
91+ MyClass();
92+ void method();
93+ };
94+ ```
95+
96+ Will produce the following code:
97+ ```rust,ignore
98+ #[repr(C)]
99+ #[derive(Debug, Copy, Clone)]
100+ pub struct MyClass {
101+ pub _address: u8,
102+ }
103+ extern "C" {
104+ #[link_name = "\u{1}_ZN7MyClass6methodEv"]
105+ pub fn MyClass_method(this: *mut MyClass);
106+ }
107+ extern "C" {
108+ #[link_name = "\u{1}_ZN7MyClassC1Ev"]
109+ pub fn MyClass_MyClass(this: *mut MyClass);
110+ }
111+ impl 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+ ```
124+ This ` MyClass::new ` Rust method can be used as a substitute for the ` MyClass `
125+ C++ constructor. However, the address of the value from inside the method will
126+ be different than from the outside. This is because the ` __bindgen_tmp ` value
127+ is moved when the ` MyClass::new ` method returns.
128+
129+ In contrast, the C++ constructor will not move the value, meaning that the
130+ address of the value will be the same inside and outside the constructor.
131+ If 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+
134+ In other words, the Rust equivalent for the following C++ code
135+
136+ ``` c++
137+ MyClass instance = MyClass();
138+ instance.method();
139+ ```
140+
141+ is not this
142+
143+ ``` rust,ignore
144+ let instance = MyClass::new();
145+ instance.method();
146+ ```
147+
148+ but this
149+
150+ ``` rust,ignore
151+ let instance = std::mem::MaybeUninit::<MyClass>::uninit();
152+ MyClass_MyClass(instance.as_mut_ptr());
153+ instance.assume_init_mut().method();
154+ ```
155+
156+ You can easily verify this fact if you provide a implementation for ` MyClass `
157+ and ` method ` that prints the the ` this ` pointer address. However, you can
158+ ignore this fact if you know that the original C++ code does not rely on the
159+ instance address in its internal logic.
0 commit comments