@@ -354,6 +354,8 @@ enum class return_value_policy : uint8_t {
354
354
reference_internal
355
355
};
356
356
357
+ class object ;
358
+
357
359
NAMESPACE_BEGIN (detail)
358
360
359
361
inline static constexpr int log2(size_t n, int k = 0 ) { return (n <= 1 ) ? k : log2 (n >> 1 , k + 1 ); }
@@ -373,6 +375,83 @@ constexpr size_t instance_simple_holder_in_ptrs() {
373
375
return size_in_ptrs (sizeof (std::shared_ptr<int >));
374
376
}
375
377
378
+ enum class HolderTypeId {
379
+ Unknown,
380
+ UniquePtr,
381
+ SharedPtr,
382
+ };
383
+ template <typename holder_type, typename SFINAE = void >
384
+ struct get_holder_type_id {
385
+ static constexpr HolderTypeId value = HolderTypeId::Unknown;
386
+ };
387
+ template <typename T>
388
+ struct get_holder_type_id <std::shared_ptr<T>, void > {
389
+ static constexpr HolderTypeId value = HolderTypeId::SharedPtr;
390
+ };
391
+ template <typename T, typename Deleter>
392
+ struct get_holder_type_id <std::unique_ptr<T, Deleter>, void > {
393
+ // TODO(eric.cousineau): Should this only specialize for `std::default_deleter`?
394
+ static constexpr HolderTypeId value = HolderTypeId::UniquePtr;
395
+ };
396
+
397
+ class holder_erased {
398
+ public:
399
+ holder_erased () = default ;
400
+ holder_erased (const holder_erased&) = default ;
401
+ holder_erased& operator =(const holder_erased&) = default ;
402
+
403
+ template <typename holder_type>
404
+ holder_erased (const holder_type* holder)
405
+ : ptr_(const_cast <holder_type*>(holder)),
406
+ type_id_ (get_holder_type_id<holder_type>::value),
407
+ is_const_(true ) {}
408
+
409
+ template <typename holder_type>
410
+ holder_erased (holder_type* holder)
411
+ : holder_erased(static_cast <const holder_type*>(holder)) {
412
+ is_const_ = false ;
413
+ }
414
+
415
+ holder_erased (const void * ptr, HolderTypeId type_id)
416
+ : ptr_(const_cast <void *>(ptr)),
417
+ type_id_(type_id),
418
+ is_const_(true ) {}
419
+
420
+ holder_erased (void * ptr, HolderTypeId type_id)
421
+ : ptr_(ptr),
422
+ type_id_(type_id),
423
+ is_const_(false ) {}
424
+
425
+ void * ptr () const { return ptr_; }
426
+ HolderTypeId type_id () const { return type_id_; }
427
+
428
+ template <typename holder_type>
429
+ holder_type& mutable_cast () const {
430
+ if (is_const_)
431
+ throw std::runtime_error (" Trying to mutate const reference?" );
432
+ return do_cast<holder_type>();
433
+ }
434
+
435
+ template <typename holder_type>
436
+ const holder_type& cast () const {
437
+ return do_cast<holder_type>();
438
+ }
439
+
440
+ operator bool () const { return ptr_; }
441
+ private:
442
+ template <typename holder_type>
443
+ holder_type& do_cast () const {
444
+ if (type_id_ != get_holder_type_id<holder_type>::value) {
445
+ throw std::runtime_error (" Mismatch on holder type." );
446
+ }
447
+ return *reinterpret_cast <holder_type*>(ptr_);
448
+ }
449
+
450
+ void * ptr_{};
451
+ HolderTypeId type_id_{HolderTypeId::Unknown};
452
+ bool is_const_{true };
453
+ };
454
+
376
455
// Forward declarations
377
456
struct type_info ;
378
457
struct value_and_holder ;
@@ -423,6 +502,26 @@ struct instance {
423
502
// / If true, get_internals().patients has an entry for this object
424
503
bool has_patients : 1 ;
425
504
505
+ typedef void (*release_to_cpp_t )(instance* inst, holder_erased external_holder, object&& obj);
506
+ typedef object (*reclaim_from_cpp_t )(instance* inst, holder_erased external_holder);
507
+
508
+ struct type_release_info_t {
509
+ // Release an instance to C++ for pure C++ instances or Python-derived classes.
510
+ release_to_cpp_t release_to_cpp = nullptr ;
511
+
512
+ // For classes wrapped in `wrapper<>`. See `move_only_holder_caster` for more info.
513
+ // Pure / direct C++ objects do not need any fancy releasing mechanisms. They are simply
514
+ // unwrapped and passed back.
515
+ bool can_derive_from_wrapper = false ;
516
+
517
+ // The holder that is contained by this class.
518
+ HolderTypeId holder_type_id = HolderTypeId::Unknown;
519
+ };
520
+ // / If the instance is a Python-derived type that is owned in C++, then this method
521
+ // / will permit the instance to be reclaimed back by Python.
522
+ // TODO(eric.cousineau): This may not be necessary. See note in `type_caster_generic::cast`.
523
+ reclaim_from_cpp_t reclaim_from_cpp = nullptr ;
524
+
426
525
// / Initializes all of the above type/values/holders data (but not the instance values themselves)
427
526
void allocate_layout ();
428
527
0 commit comments