@@ -79,3 +79,81 @@ cannot translate into Rust:
79
79
large structs in C that would not fit into a register. This also applies to types with any base classes
80
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
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
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