Support for tp_free and/or custom delete #932
Unanswered
Walter-Reactor
asked this question in
Q&A
Replies: 2 comments 6 replies
-
For reference, the code below is enough to do what I need, but it's a bit ugly & I'd like to either improve it or upstream a nicer way. static void (*nb_tp_dealloc)(void *) = nullptr;
void diplomat_tp_dealloc(PyObject *self)
{
using namespace nb::detail;
printf("diplomat_tp_dealloc %d\n", __LINE__);
PyTypeObject *tp = Py_TYPE(self);
nb_inst *inst = (nb_inst *)self;
if (inst->cpp_delete)
{
inst->cpp_delete = false;
printf("diplomat_tp_dealloc %d\n", __LINE__);
auto tp_free = (freefunc)(PyType_GetSlot(tp, Py_tp_free));
(*tp_free)(self);
}
(*nb_tp_dealloc)(self);
}
struct Dummy
{
};
NB_MODULE(somelib, somelib_mod)
{
{
nb::class_<Dummy> dummy(somelib_mod, "__dummy__");
nb_tp_dealloc = (void (*)(void *))nb::type_get_slot(dummy, Py_tp_dealloc);
}
...
PyType_Slot slots[] = {
{Py_tp_free, (void *)MyType::operator delete },
{Py_tp_dealloc, (void *)diplomat_tp_dealloc},
{0, nullptr}};
nb::class_<MyType>(somelib_mod, "MyType", nb::type_slots(slots))
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
Nanobind doesn't use
It uses those operations because those same objects were also allocated in a custom way:
Of your various options, I would be open to approach 2, since it does not impose additional runtime costs. |
Beta Was this translation helpful? Give feedback.
6 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I'm aware that generally speaking nanobind does not support c++ types which overload operators new/delete, however I'm working on a project where, at the very least, I need to support custom deleters. I'd prefer not to give up on nanobind and resort to pybind11, so I've experimented with overriding the tp_dealloc slot. Unfortunately the
inst_dealloc
doesn't have a header declaration, so I've had to copy/paste the definition. In doing so, I noticed that the implementation never appears to call tp_free, even though there are some ifdefs that store that function pointer. Am I perhaps missing something?Solutions that could work for me that I can think of:
inst_dealloc
which will calltp_free
instead of an untypeddelete
, and put my custom deleter in the tp_free slot.def(nb::delete<T>())
?Would the nanobind maintainers be open to a patch adding that kind of support?
For background, I'm working on a project exposing an API written in Rust to multiple languages via a bunch of #[repr(C)] structs and pointers, and since I already have to write codegen for C++, I've been using nanobind to create the python bindings. The only hitch is that almost everything is allocated by the rust heap, and must be freed by it.
Beta Was this translation helpful? Give feedback.
All reactions