Creating a shared_ptr from a unique_ptr with custom deleter

125 views
Skip to first unread message

buc...@gmail.com

unread,
Jul 27, 2016, 12:53:13 AM7/27/16
to cython-users
(My C++ knowledge is a bit weak, so there is hopefully an obvious answer to this.)

In PR https://github.com/cython/cython/commit/b591de14a09ca4036d8b4f3fb9612b67533088b4#diff-78bb65c584df19f9ecca5ba04a0bad2eR7 support for unique_ptr with custom deleter was added. I'm using this to wrap an existing Cython object and it's working fine. What's not working fine is a call like this:

cdef unique_ptr[A,D] a = (....)
cdef shared_ptr[A] a_sh = shared_ptr[A](move(a)))

Essentially, the C++ code I'm wrapping returns a unique_ptr with a custom destructor and I need a shared_ptr instead. I notice that there is no shared_ptr constructor in https://github.com/cython/cython/pull/406/commits/411668ee116090128d34a7ca8350bf02d30de715#diff-78bb65c584df19f9ecca5ba04a0bad2eR44 that accepts a unique_ptr[T,D], which is probably what I'm looking for. I've been trying to write my own cdef extern specifier for a shared_ptr cpp class, but I haven't been able to make it compile.

I've found C++ code that basically does this:

template <typename T, typename D>
std::shared_ptr<T> shared_ptr_from_unique(std::unique_ptr<T, D>&& ptr) {
    return std::shared_ptr<T>(std::move(ptr));
}

I'm going to try wrapping this code next, but I was hoping someone could tell me how to do this using pure Cython in the meantime.

Thanks,
Dusty

Kevin Thornton

unread,
Jul 27, 2016, 10:10:53 AM7/27/16
to cython-users


On Tuesday, July 26, 2016 at 9:53:13 PM UTC-7, buc...@gmail.com wrote:
(My C++ knowledge is a bit weak, so there is hopefully an obvious answer to this.)

In PR https://github.com/cython/cython/commit/b591de14a09ca4036d8b4f3fb9612b67533088b4#diff-78bb65c584df19f9ecca5ba04a0bad2eR7 support for unique_ptr with custom deleter was added. I'm using this to wrap an existing Cython object and it's working fine. What's not working fine is a call like this:

cdef unique_ptr[A,D] a = (....)
cdef shared_ptr[A] a_sh = shared_ptr[A](move(a)))

Essentially, the C++ code I'm wrapping returns a unique_ptr with a custom destructor and I need a shared_ptr instead. I notice that there is no shared_ptr constructor in https://github.com/cython/cython/pull/406/commits/411668ee116090128d34a7ca8350bf02d30de715#diff-78bb65c584df19f9ecca5ba04a0bad2eR44 that accepts a unique_ptr[T,D], which is probably what I'm looking for. I've been trying to write my own cdef extern specifier for a shared_ptr cpp class, but I haven't been able to make it compile.

No such constructor exists in Cython because Cython does not support C++11 move semantics.

To do it in Cython:

from cython.operator cimport dereference as deref

#assume up is a unique_ptr[FOO], and assume FOO 
#is a copyable type
cdef shared_ptr[FOO] x = shared_ptr[FOO](new foo(deref(up.get()))
up.reset(NULL) #Untested--nullptr should be preferred here, but Cython does not support that.

This should all work if the types are [FOO,DELETER], too.

The main problem is that Cython is supporting C++98 and not modern C++.

Kevin Thornton

unread,
Jul 27, 2016, 12:59:51 PM7/27/16
to cython-users
Quick follow-up:

My bad, Cython does support nullptr via "from libcpp cimport nullptr".

My example of Cython-only code was bad.  Ideally, the deleter should also be gotten from the unique_ptr, but it looks like Cython doesn't wrap that constructor.

Your best bet is to wrap the C++ code yourself as you mentioned.
Reply all
Reply to author
Forward
0 new messages