@@ -47,13 +47,14 @@ static void *nb_foreign_from_python(pymb_binding *binding,
4747 PyObject *obj),
4848 void *keep_referenced_ctx) noexcept {
4949 cleanup_list cleanup{nullptr };
50+ uint8_t flags = (uint8_t ) cast_flags::not_foreign;
51+ if (convert)
52+ flags |= (uint8_t ) cast_flags::convert;
5053 auto *td = (type_data *) binding->context ;
5154 if (td->align == 0 ) { // enum
5255 int64_t value;
5356 if (keep_referenced &&
54- enum_from_python (td->type , pyobj, &value, td->size ,
55- convert ? uint8_t (cast_flags::convert) : 0 ,
56- nullptr )) {
57+ enum_from_python (td->type , pyobj, &value, td->size , flags, nullptr )) {
5758 bytes holder{(uint8_t *) &value + NB_BIG_ENDIAN * (8 - td->size ),
5859 td->size };
5960 keep_referenced (keep_referenced_ctx, holder.ptr ());
@@ -63,8 +64,7 @@ static void *nb_foreign_from_python(pymb_binding *binding,
6364 }
6465
6566 void *result = nullptr ;
66- bool ok = nb_type_get (td->type , pyobj,
67- convert ? uint8_t (cast_flags::convert) : 0 ,
67+ bool ok = nb_type_get (td->type , pyobj, flags,
6868 keep_referenced ? &cleanup : nullptr , &result);
6969 if (keep_referenced) {
7070 // Move temporary references from our `cleanup_list` to our caller's
@@ -109,7 +109,8 @@ static PyObject *nb_foreign_to_python(pymb_binding *binding,
109109 // unless a pyobject wrapper already exists.
110110 rvp = rv_policy::none;
111111 }
112- return nb_type_put (td->type , cobj, rvp, &cleanup, nullptr );
112+ return nb_type_put (td->type , cobj, rvp, &cleanup,
113+ /* is_new */ nullptr , /* allow_foreign */ false );
113114}
114115
115116static int nb_foreign_keep_alive (PyObject *nurse,
@@ -153,10 +154,12 @@ static int nb_foreign_translate_exception(void *eptr) noexcept {
153154 std::rethrow_exception (e);
154155 } catch (python_error &e) {
155156 e.restore ();
157+ return 1 ;
156158 } catch (builtin_exception &e) {
157159 if (!set_builtin_exception_status (e))
158160 PyErr_SetString (PyExc_SystemError, " foreign function threw "
159161 " nanobind::next_overload()" );
162+ return 1 ;
160163 } catch (...) { e = std::current_exception (); }
161164 return 0 ;
162165}
@@ -521,10 +524,10 @@ void *nb_type_try_foreign(nb_internals *internals_,
521524#if defined(NB_FREE_THREADED)
522525 auto per_thread_guard = nb_type_lock_c2p_fast (internals_);
523526 nb_type_map_fast &type_c2p_fast = *per_thread_guard;
524- uint32_t updates_count = per_thread_guard.updates_count ();
525527#else
526528 nb_type_map_fast &type_c2p_fast = internals_->type_c2p_fast ;
527529#endif
530+ uint32_t update_count = type_c2p_fast.update_count ;
528531 do {
529532 // We assume nb_type_c2p already ran for this type, so that there's
530533 // no need to handle a cache miss here.
@@ -563,16 +566,16 @@ void *nb_type_try_foreign(nb_internals *internals_,
563566 return result;
564567
565568#if defined(NB_FREE_THREADED)
566- // Re-acquire lock to continue iteration. If we missed an
567- // update while the lock was released, start our lookup over
568- // in case the update removed the node we're on.
569+ // Re-acquire lock to continue iteration
569570 per_thread_guard = nb_type_lock_c2p_fast (internals_);
570- if (per_thread_guard.updates_count () != updates_count) {
571+ #endif
572+ // If we missed an update during attempt(), start our lookup
573+ // over in case the update removed the node we're on.
574+ if (type_c2p_fast.update_count != update_count) {
571575 // Concurrent update occurred; retry
572- updates_count = per_thread_guard. updates_count () ;
576+ update_count = type_c2p_fast. update_count ;
573577 break ;
574578 }
575- #endif
576579 }
577580 current = current->next ;
578581 }
0 commit comments