Open Volker-Weissmann opened 4 years ago
From the bindgen
user guide,
using those types in Rust will be nowhere near as nice as using them in C++. You will have to manually call constructors, destructors, overloaded operators, etc yourself.
I am not sure if that is the end of the story, but I think your reasonable request might be more than bindgen
can reasonably provide.
Yes, you need to implement Drop
yourself, because it can cause unsoundness otherwise.
For example, if bindgen would implement Drop
by default, dropping Outer
would end up calling ~Inner
twice, once from Rust, once from C++, which is bad.
We could fix that using ManuallyDrop
for members of structs that have destructors nowadays, I think.
Two things:
You said that #1841 is the same as this issue and renamed this issue. But adding the default destructor/default constructor and calling the deconstructor using the drop trait are two seperate things. You can do the first thing without doing the second.
I understand and could reproduce the problem of ~Inner
being called twice. I think that some kind of hacky solution (maybe using ManuallyDrop
) would be really valuable. One way to do this would be to autogen the following:
Outer* wrap_outer_construct() {
return new Outer();
}
void wrap_outer_destruct(Outer *ptr) {
assert(ptr != NULL);
delete ptr;
}
struct wrap_outer {
ptr: *mut Outer
}
impl wrap_outer {
fn new() -> wrap_outer {
let cptr = unsafe {
wrap_outer_construct()
};
wrap_outer{ptr: cptr}
}
}
impl Drop for wrap_outer {
fn drop(&mut self) {
unsafe {
wrap_outer_destruct(self.ptr);
}
}
}
The disadvantage of this is that you can no longer access the member variables (or autogen getters/setters?).
You said that #1841 is the same as this issue and renamed this issue. But adding the default destructor/default constructor and calling the deconstructor using the drop trait are two seperate things. You can do the first thing without doing the second.
Well, kinda, right? If we auto-implement drop, then default constructors between Rust and C++ behave the same don't they?
I'm not sure under which circumstances a C++ compiler emits symbols for a default constructor, if it does at all. If you have info on that we can try to elaborate a solution for it.
You said that #1841 is the same as this issue and renamed this issue. But adding the default destructor/default constructor and calling the deconstructor using the drop trait are two seperate things. You can do the first thing without doing the second.
Well, kinda, right? If we auto-implement drop, then default constructors between Rust and C++ behave the same don't they?
I'm not sure under which circumstances a C++ compiler emits symbols for a default constructor, if it does at all. If you have info on that we can try to elaborate a solution for it.
No. #1841 is about pub fn destruct(&mut self)
being called automatically, #1840 is about pub fn destruct(&mut self)
existing if there is no ~MyClass()
in the C++ code. The reason I opened #1840 is that adding ~MyClass(){}
does not change anything in a pure C++ program, but it changes something for bindgen.
I think its safe to automatically generate Drop
for opaque types as destructors of inner fields will not be called twice.
@emilio what do you think?
Consider the following C++ code:
If you use bindgen to execute
You get the output
Which is also the output of the C++ code
If we now remove the ~Outer() deconstructor, this C++ code outputs
But the rust code
no longer compilers because Outer::destruct does not exist and the rust code
just outputs
which might result in memory leaks or similar bugs. A similar problem arises if you remove the default constructor.
Is it possible to automatically add constructors and destructors that call the constructors and destructors of the member variables?