@@ -47,13 +47,14 @@ static void *nb_foreign_from_python(pymb_binding *binding,
47
47
PyObject *obj),
48
48
void *keep_referenced_ctx) noexcept {
49
49
cleanup_list cleanup{nullptr };
50
+ uint8_t flags = (uint8_t ) cast_flags::not_foreign;
51
+ if (convert)
52
+ flags |= (uint8_t ) cast_flags::convert;
50
53
auto *td = (type_data *) binding->context ;
51
54
if (td->align == 0 ) { // enum
52
55
int64_t value;
53
56
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 )) {
57
58
bytes holder{(uint8_t *) &value + NB_BIG_ENDIAN * (8 - td->size ),
58
59
td->size };
59
60
keep_referenced (keep_referenced_ctx, holder.ptr ());
@@ -63,8 +64,7 @@ static void *nb_foreign_from_python(pymb_binding *binding,
63
64
}
64
65
65
66
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,
68
68
keep_referenced ? &cleanup : nullptr , &result);
69
69
if (keep_referenced) {
70
70
// Move temporary references from our `cleanup_list` to our caller's
@@ -109,7 +109,8 @@ static PyObject *nb_foreign_to_python(pymb_binding *binding,
109
109
// unless a pyobject wrapper already exists.
110
110
rvp = rv_policy::none;
111
111
}
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 );
113
114
}
114
115
115
116
static int nb_foreign_keep_alive (PyObject *nurse,
@@ -153,10 +154,12 @@ static int nb_foreign_translate_exception(void *eptr) noexcept {
153
154
std::rethrow_exception (e);
154
155
} catch (python_error &e) {
155
156
e.restore ();
157
+ return 1 ;
156
158
} catch (builtin_exception &e) {
157
159
if (!set_builtin_exception_status (e))
158
160
PyErr_SetString (PyExc_SystemError, " foreign function threw "
159
161
" nanobind::next_overload()" );
162
+ return 1 ;
160
163
} catch (...) { e = std::current_exception (); }
161
164
return 0 ;
162
165
}
@@ -521,10 +524,10 @@ void *nb_type_try_foreign(nb_internals *internals_,
521
524
#if defined(NB_FREE_THREADED)
522
525
auto per_thread_guard = nb_type_lock_c2p_fast (internals_);
523
526
nb_type_map_fast &type_c2p_fast = *per_thread_guard;
524
- uint32_t updates_count = per_thread_guard.updates_count ();
525
527
#else
526
528
nb_type_map_fast &type_c2p_fast = internals_->type_c2p_fast ;
527
529
#endif
530
+ uint32_t update_count = type_c2p_fast.update_count ;
528
531
do {
529
532
// We assume nb_type_c2p already ran for this type, so that there's
530
533
// no need to handle a cache miss here.
@@ -563,16 +566,16 @@ void *nb_type_try_foreign(nb_internals *internals_,
563
566
return result;
564
567
565
568
#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
569
570
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) {
571
575
// Concurrent update occurred; retry
572
- updates_count = per_thread_guard. updates_count () ;
576
+ update_count = type_c2p_fast. update_count ;
573
577
break ;
574
578
}
575
- #endif
576
579
}
577
580
current = current->next ;
578
581
}
0 commit comments