Skip to content

Commit

Permalink
be more tolerant of duplicate type bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
wjakob committed Jun 3, 2023
1 parent 188dd5d commit f3b0e6c
Showing 3 changed files with 25 additions and 9 deletions.
15 changes: 13 additions & 2 deletions docs/api_core.rst
Original file line number Diff line number Diff line change
@@ -1535,13 +1535,24 @@ Class binding

.. cpp:class:: template <typename T, typename... Ts> class_ : public object

Binding helper class to expose a custom C++ type `T` (declared using either the ``class`` or ``struct`` keyword)
in Python.
Binding helper class to expose a custom C++ type `T` (declared using either
the ``class`` or ``struct`` keyword) in Python.

The variable length parameter `Ts` is optional and can be used to specify
the base class of `T` and/or an alias needed to realize :ref:`trampoline
classes <trampolines>`.

When the type ``T`` was previously already registered (either within the
same extension or another extension), the the ``class_<..>`` declaration is
redundant. nanobind will print a warning message in this case:

.. code-block:: text
RuntimeWarning: nanobind: type 'MyType' was already registered!
The ``class_<..>`` instance will subsequently wrap the original type object
instead of creating a new one.

.. cpp:function:: template <typename... Extra> class_(handle scope, const char * name, const Extra &... extra)

Bind the type `T` to the identifier `name` within the scope `scope`. The
2 changes: 1 addition & 1 deletion src/nb_func.cpp
Original file line number Diff line number Diff line change
@@ -701,7 +701,7 @@ static PyObject *nb_func_vectorcall_simple(PyObject *self,
PyObject *result = nullptr,
*self_arg = (is_method && nargs_in > 0) ? args_in[0] : nullptr;

/// Small array holding temporaries (implicit conversion/*args/**kwargs)
// Small array holding temporaries (implicit conversion/*args/**kwargs)
cleanup_list cleanup(self_arg);

// Handler routine that will be invoked in case of an error condition
17 changes: 11 additions & 6 deletions src/nb_type.cpp
Original file line number Diff line number Diff line change
@@ -669,6 +669,16 @@ PyObject *nb_type_new(const type_init_data *t) noexcept {
object modname;
PyObject *mod = nullptr;

// Update hash table that maps from std::type_info to Python type
auto [it, success] =
internals.type_c2p.try_emplace(std::type_index(*t->type), nullptr);
if (!success) {
PyErr_WarnFormat(PyExc_RuntimeWarning, 1, "nanobind: type '%s' was already registered!\n", t->name);
PyObject *tp = (PyObject *) it->second->type_py;
Py_INCREF(tp);
return tp;
}

if (t->scope != nullptr) {
if (PyModule_Check(t->scope)) {
mod = t->scope;
@@ -850,12 +860,7 @@ PyObject *nb_type_new(const type_init_data *t) noexcept {
if (modname.is_valid())
setattr(result, "__module__", modname.ptr());

// Update hash table that maps from std::type_info to Python type
auto [it, success] =
internals.type_c2p.try_emplace(std::type_index(*t->type), to);
if (!success)
fail("nanobind::detail::nb_type_new(\"%s\"): type was already "
"registered!", t->name);
internals.type_c2p[std::type_index(*t->type)] = to;

return result;
}

0 comments on commit f3b0e6c

Please sign in to comment.