-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom owning pointer #605
Comments
The output doesn't indicate a problem: the m.def("print_addr", [](A *a) { std::cout << (void *) a << std::endl; }); and then call it from the Python side: you should see the same address. |
Fair point (though I do not want my A object to be copied if I return a pointer, do I?), but I'm afraid that does not shed another light on the case:
Besides, I've been printing before what constructors of the smart pointer are being called, and I twice get a constructor invocation with a raw pointer, instead of a move (or copy, e.g. in the legacy auto_ptr case) constructor. |
I can reproduce the issue. Looks like a bug in pybind11, specifically with move-only holders that aren't exactly |
Awesome! (For the record, with the old, deprecated std::auto_ptr, which did not have a move-constructor yet, the same thing happens. So it's not for 'move only types', but also for smart pointers that handle things in a copy constructor.) |
Are you sure about The move-only holder issue should be resolved by PR #607. |
I do seem to be getting the same, yes, both with template <class T>
class TestPtr : public std::auto_ptr<T>
{
public:
TestPtr(T *t) : std::auto_ptr<T>(t) { std::cout << "TestPtr<T>::TestPtr<T>(T *) - " << (void *) this << std::endl; }
TestPtr(TestPtr<T> &t) : std::auto_ptr<T>(t) { std::cout << "TestPtr<T>::TestPtr<T>(TestPtr<T> &) - " << (void *) this << std::endl; }
TestPtr(TestPtr<T> &&t) : std::auto_ptr<T>(t) { std::cout << "TestPtr<T>::TestPtr<T>(TestPtr<T> &&) - " << (void *) this << std::endl; }
~TestPtr() { std::cout << "TestPtr<T>::~TestPtr<T>() - " << (void *) this << std::endl; }
};
No explicit segfault, this time, but I think that's just lucky undefined behavior, because the destructor is called twice on the same object. Do note that the 'copy constructor' of |
You're right. I seem to have accidentally tested |
Somehow, there is a weird chain of dependencies and consequences there, isn't it? Because it is not copy-constructible, it will be a "move-only holder", but because there is no move constructor, this semi-copy-contructor |
I agree that move constructors should be preferred, but there's a bit of a tradeoff there. Due to Python's dynamic typing, pybind11 relies on runtime type information to properly cast stuff back and forth. C++'s static type information (lvalue vs rvalue, const vs mutable) is lost in the process. This information needs to be encoded into runtime data as well. This is already done for the actual objects, but not for the object holders. Most of the time this doesn't matter since most holders behave somewhat like |
Ok, fair enough, I don't have a good view on the pybind11 internals. And even if you're going from C++ to Python (with Either way, my immediate problem is solved; thank you very much for this quick solution! |
I find myself unable to create and register a smart pointer that would have the same basic functionality as std::unique_ptr. A returned smart pointer does not seem to be moved, and instead another one is created on the same raw pointer.
A small example:
where
my_unique_ptr.h
is a copy of the GCCstd::unique_ptr
implementation, just to be sure there is nothing wrong with the actual smart pointer type I need to wrap: https://gist.github.com/YannickJadoul/fe5b318e9cbbd65a6e31ead7bad1599f (Please note that in my actual project, I am wrapping existing code by someone else, and there is not an obvious way of changing the custom smart pointer for a standard std::unique_ptr, although I certainly agree that could be infinitely better.)As running
test.A.make()
results in the following output ...... you can see how quitting my Python interpreter afterwards results in a beautiful segfault.
So, am I misusing this nice pybind11 project and its smart pointers, or is this an unforeseen feature (aka bug)?
The text was updated successfully, but these errors were encountered: