73#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_PYSHADOW_OBJECT_H
74#define LASS_GUARDIAN_OF_INCLUSION_UTIL_PYSHADOW_OBJECT_H
87using TShadoweeID = num::TuintPtr;
104class LASS_PYTHON_DLL ShadowBaseCommon:
public PyObjectPlus
107 static TPyObjPtr findShadowObject(TShadoweeID shadoweeID, ShadoweeConstness constness);
111 ~ShadowBaseCommon()
override;
113 void registerShadowee(TShadoweeID shadoweeID, ShadoweeConstness constness);
114 void unregisterShadowee(TShadoweeID shadoweeID, ShadoweeConstness constness);
116 typedef std::pair<TShadoweeID, ShadoweeConstness> TCacheKey;
120 std::size_t operator()(
const TCacheKey& key)
const
122 std::size_t h1 = std::hash<TShadoweeID>()(key.first);
123 std::size_t h2 = std::hash<ShadoweeConstness>()(key.second);
128 typedef std::unordered_map<TCacheKey, ShadowBaseCommon*, CacheKeyHash> TCache;
129 ShadowBaseCommon(
const ShadowBaseCommon&);
130 ShadowBaseCommon& operator=(
const ShadowBaseCommon&);
132 static TCache& cache();
139struct IsShadowClass:
public meta::IsDerived<T, ShadowBaseCommon>
149 enum { isShadow = IsShadowClass<T>::value };
153 template <
typename U,
bool shadow>
156 typedef typename U::TShadoweePtr TCppClassPtr;
157 typedef typename U::TConstShadoweePtr TConstCppClassPtr;
158 typedef typename U::TShadowPtr TPyClassPtr;
159 typedef typename U::TShadowee TCppClass;
160 static int getObject(U* obj, TCppClassPtr& value)
162 typedef typename U::TPointerTraits TPointerTraits;
163 const TCppClassPtr p = TPointerTraits::staticCast(obj->cppObject());
164 if (TPointerTraits::isEmpty(p))
166 PyErr_Format(PyExc_TypeError,
"PyObject is a const %s", T::_lassPyClassDef.name());
172 static int getObject(U* obj, TConstCppClassPtr& value)
174 typedef typename U::TConstPointerTraits TConstPointerTraits;
175 value = TConstPointerTraits::staticCast(obj->constCppObject());
176 if (TConstPointerTraits::isEmpty(value))
178 PyErr_Format(PyExc_TypeError,
"Trying to dereference null-PyObject of type %s", T::_lassPyClassDef.name());
183 template <
typename Ptr>
static TPyClassPtr buildObject(
const Ptr& value)
185 return U::make(value);
189 template <
typename U>
190 struct Impl<U, false>
192 typedef typename PyObjectPtr<U>::Type TPyClassPtr;
193 typedef TPyClassPtr TCppClassPtr;
194 typedef typename PyObjectPtr<const U>::Type TConstCppClassPtr;
196 static int getObject(U* obj, TPyClassPtr& value)
201 static int getObject(U* obj, TConstCppClassPtr& value)
206 static const TPyClassPtr& buildObject(
const TPyClassPtr& value)
213 typedef Impl<T, isShadow> TImpl;
215 static bool checkSubType(PyObject* obj)
218 if (!PyType_IsSubtype(obj->ob_type , T::_lassPyClassDef.type() ))
220 PyErr_Format(PyExc_TypeError,
"%s not castable to %s", obj->ob_type->tp_name, T::_lassPyClassDef.name());
228 typedef typename TImpl::TCppClass TCppClass;
229 typedef typename TImpl::TCppClassPtr TCppClassPtr;
230 typedef typename TImpl::TConstCppClassPtr TConstCppClassPtr;
231 typedef typename TImpl::TPyClassPtr TPyClassPtr;
232 typedef int (*TImplicitConverter)(PyObject* obj, TCppClassPtr&);
234 template <
typename Ptr>
static int getObject(PyObject* obj, Ptr& value)
241 if (PyType_IsSubtype(obj->ob_type , T::_lassPyClassDef.type()))
243 return TImpl::getObject(
static_cast<T*
>(obj), value);
246 if (tryImplicitConverters(obj, p) != 0)
253 static int getObject(PyObject* obj, TCppClass& value)
257 PyErr_Format(PyExc_TypeError,
"None not castable to %s", T::_lassPyClassDef.name());
261 if (obj->ob_type == T::_lassPyClassDef.type())
263 if (TImpl::getObject(
static_cast<T*
>(obj), p) != 0)
271 if (tryImplicitConverters(obj, p2) != 0)
281 LASS_PYTHON_CATCH_AND_RETURN_EX(1)
284 template <typename Ptr> static TPyClassPtr buildObject(const Ptr& value)
286 return TImpl::buildObject(value);
288 static TPyClassPtr buildObject(
const TCppClass& value)
290 TCppClassPtr p(
new TCppClass(value));
291 return buildObject(p);
293 template <
typename Deleter>
294 static TPyClassPtr buildObject(std::unique_ptr<TCppClass, Deleter>&& value)
296 return buildObject(TCppClassPtr(std::move(value)));
298 static void addConverter(TImplicitConverter converter)
300 TImplicitConverterList* converters = implicitConverters();
301 converters->push_back(converter);
305 typedef std::vector<TImplicitConverter> TImplicitConverterList;
306 static TImplicitConverterList* implicitConverters_;
308 static int tryImplicitConverters(PyObject* obj, TCppClassPtr& p)
310 const TImplicitConverterList* converters = implicitConverters();
313 for (
typename TImplicitConverterList::const_iterator i = converters->begin(); i != converters->end(); ++i)
315 if ((*i)(obj, p) == 0)
322 PyErr_Format(PyExc_TypeError,
"%s not convertable to %s", obj->ob_type->tp_name, T::_lassPyClassDef.name());
326 static TImplicitConverterList* implicitConverters()
328 void*& slot = T::_lassPyClassDef.implicitConvertersSlot_;
331 slot =
new TImplicitConverterList;
333 return static_cast<TImplicitConverterList*
>(slot);
339template <
typename ShadowType,
typename DerivedMakers>
340typename ShadowType::TShadowPtr makeShadow(
341 const typename ShadowType::TConstShadoweePtr& shadowee,
const DerivedMakers* derivedMakers,
342 impl::ShadoweeConstness constness)
344 typedef typename ShadowType::TShadowPtr TShadowPtr;
345 typedef typename ShadowType::TConstPointerTraits TConstPointerTraits;
347 LASS_ASSERT(!TConstPointerTraits::isEmpty(shadowee));
348 if (
const auto p = impl::ShadowBaseCommon::findShadowObject(TConstPointerTraits::id(shadowee), constness))
350 LASS_ASSERT(PyObject_IsInstance(p.get(),
reinterpret_cast<PyObject*
>(ShadowType::_lassPyClassDef.type())));
351 return p.template staticCast<ShadowType>();
355 for (
typename DerivedMakers::const_iterator i = derivedMakers->begin(); i != derivedMakers->end(); ++i)
357 if (
const TShadowPtr p = (*i)(shadowee, constness))
363 return TShadowPtr(impl::fixObjectType(
new ShadowType(shadowee, constness)));
366template <
typename Makers,
typename Maker>
void registerMaker(Makers*& makers, Maker maker)
372 makers->push_back(maker);
375template <
typename DestPyType,
typename SourceCppType>
376int defaultConvertor(PyObject*
object,
typename lass::python::impl::ShadowTraits<DestPyType>::TCppClassPtr& p)
378 typedef typename lass::python::impl::ShadowTraits<DestPyType>::TCppClass TCppClass;
379 typedef typename lass::python::impl::ShadowTraits<DestPyType>::TCppClassPtr TPtr;
380 SourceCppType source;
381 if (pyGetSimpleObject(
object, source) != 0)
385 p = TPtr(
new TCppClass(source));
392template <
typename T,
template <
typename,
typename>
class S = util::ObjectStorage,
typename C = util::DefaultCounter>
393struct SharedPointerTraits
395 typedef util::SharedPtr<T, S, C> TPtr;
396 template <
typename U>
struct Rebind
398 typedef SharedPointerTraits<U, S, C> Type;
400 static void acquire(
const TPtr&) {}
401 static void release(
const TPtr&) {}
402 static bool isEmpty(
const TPtr& p)
406 static T* get(
const TPtr& p)
410 static TShadoweeID id(
const TPtr& p)
412 return reinterpret_cast<TShadoweeID
>(p.get());
414 template <
typename U>
static TPtr staticCast(
const util::SharedPtr<U, S, C>& p)
416 return p.template staticCast<T>();
418 template <
typename U>
static TPtr dynamicCast(
const util::SharedPtr<U, S, C>& p)
420 return p.template dynamicCast<T>();
422 template <
typename U>
static TPtr constCast(
const util::SharedPtr<U, S, C>& p)
424 return p.template constCast<T>();
430struct NakedPointerTraits
433 template <
typename U>
struct Rebind
435 typedef NakedPointerTraits<U> Type;
437 static void acquire(TPtr) {}
438 static void release(TPtr) {}
439 static bool isEmpty(TPtr p)
443 static T* get(TPtr p)
447 static TShadoweeID id(TPtr p)
449 return reinterpret_cast<TShadoweeID
>(p);
451 template <
typename U>
static TPtr staticCast(U* p)
453 return static_cast<TPtr
>(p);
455 template <
typename U>
static TPtr dynamicCast(U* p)
457 return dynamic_cast<TPtr
>(p);
459 template <
typename U>
static TPtr constCast(U* p)
461 return const_cast<TPtr
>(p);
467struct StdSharedPointerTraits
469 typedef std::shared_ptr<T> TPtr;
470 template <
typename U>
struct Rebind
472 typedef StdSharedPointerTraits<U> Type;
474 static void acquire(
const TPtr&) {}
475 static void release(
const TPtr&) {}
476 static bool isEmpty(
const TPtr& p)
480 static T* get(
const TPtr& p)
484 static TShadoweeID id(TPtr p)
486 return reinterpret_cast<TShadoweeID
>(p.get());
488 template <
typename U>
static TPtr staticCast(
const std::shared_ptr<U>& p)
490 return std::static_pointer_cast<T>(p);
492 template <
typename U>
static TPtr dynamicCast(
const std::shared_ptr<U>& p)
494 return std::dynamic_pointer_cast<T>(p);
496 template <
typename U>
static TPtr constCast(
const std::shared_ptr<U>& p)
498 return std::const_pointer_cast<T>(p);
508 typename ShadoweeType,
509 typename ParentShadowType,
510 typename PointerTraits = SharedPointerTraits<ShadoweeType>
512class ShadowClass:
public ParentShadowType
515 typedef ShadoweeType TShadowee;
516 typedef ShadowType TShadow;
517 typedef ParentShadowType TParentShadow;
518 typedef typename PointerTraits::template Rebind<ShadoweeType>::Type TPointerTraits;
519 typedef typename PointerTraits::template Rebind<const ShadoweeType>::Type TConstPointerTraits;
520 typedef typename TPointerTraits::TPtr TShadoweePtr;
521 typedef typename TConstPointerTraits::TPtr TConstShadoweePtr;
522 typedef typename PyObjectPtr<ShadowType>::Type TShadowPtr;
524 static TShadowPtr make(
const TShadoweePtr& shadowee)
526 return impl::makeShadow<ShadowType>(shadowee, derivedMakers_, impl::scNonConst);
528 static TShadowPtr make(
const TConstShadoweePtr& shadowee)
530 return impl::makeShadow<ShadowType>(shadowee, derivedMakers_, impl::scConst);
532 static void registerWithParent()
534 ParentShadowType::registerDerivedMaker(ShadowClass::makeParent);
538 typedef TShadowPtr (*TDerivedMaker)(
const TConstShadoweePtr&, impl::ShadoweeConstness);
540 ShadowClass(
const TConstShadoweePtr& shadowee, impl::ShadoweeConstness constness):
541 ParentShadowType(shadowee, constness)
544 static void registerDerivedMaker(TDerivedMaker derivedMaker)
546 impl::registerMaker(derivedMakers_, derivedMaker);
550 typedef std::vector<TDerivedMaker> TDerivedMakers;
552 typedef typename TParentShadow::TConstShadoweePtr TParentConstShadoweePtr;
553 typedef typename TParentShadow::TShadowPtr TParentShadowPtr;
555 static TParentShadowPtr makeParent(
const TParentConstShadoweePtr& shadowee, impl::ShadoweeConstness constness)
557 const TConstShadoweePtr p = TConstPointerTraits::dynamicCast(shadowee);
558 if (TConstPointerTraits::isEmpty(p))
560 return TParentShadowPtr();
562 return impl::makeShadow<ShadowType>(p, derivedMakers_, constness);
565 static TDerivedMakers* derivedMakers_;
568template <
typename S,
typename T,
typename P,
typename PT>
569typename ShadowClass<S, T, P, PT>::TDerivedMakers* ShadowClass<S, T, P, PT>::derivedMakers_ = 0;
576 typename ShadoweeType,
577 typename PointerTraits
579class ShadowClass<ShadowType, ShadoweeType, PyObjectPlus, PointerTraits>:
public impl::ShadowBaseCommon
582 typedef ShadoweeType TShadowee;
583 typedef ShadowType TShadow;
584 typedef typename PointerTraits::template Rebind<ShadoweeType>::Type TPointerTraits;
585 typedef typename PointerTraits::template Rebind<const ShadoweeType>::Type TConstPointerTraits;
586 typedef typename TPointerTraits::TPtr TShadoweePtr;
587 typedef typename TConstPointerTraits::TPtr TConstShadoweePtr;
588 typedef typename PyObjectPtr<ShadowType>::Type TShadowPtr;
590 const TShadoweePtr cppObject()
const
592 if (constness_ == impl::scConst)
594 return TShadoweePtr();
596 return TPointerTraits::constCast(shadowee_);
598 const TConstShadoweePtr& constCppObject()
const
602 static TShadowPtr make(
const TShadoweePtr& shadowee)
604 return impl::makeShadow<ShadowType>(shadowee, derivedMakers_, impl::scNonConst);
606 static TShadowPtr make(
const TConstShadoweePtr& shadowee)
608 return impl::makeShadow<ShadowType>(shadowee, derivedMakers_, impl::scConst);
610 static void registerWithParent()
614 typedef TShadowPtr (*TDerivedMaker)(
const TConstShadoweePtr&, impl::ShadoweeConstness);
615 ShadowClass(
const TConstShadoweePtr& shadowee, impl::ShadoweeConstness constness):
617 constness_(constness)
619 TConstPointerTraits::acquire(shadowee_);
620 impl::ShadowBaseCommon::registerShadowee(TConstPointerTraits::id(shadowee_), constness_);
624 impl::ShadowBaseCommon::unregisterShadowee(TConstPointerTraits::id(shadowee_), constness_);
625 TConstPointerTraits::release(shadowee_);
627 static void registerDerivedMaker(TDerivedMaker derivedMaker)
629 impl::registerMaker(derivedMakers_, derivedMaker);
632 typedef std::vector<TDerivedMaker> TDerivedMakers;
634 static TDerivedMakers* derivedMakers_;
635 TConstShadoweePtr shadowee_;
636 impl::ShadoweeConstness constness_;
639template <
typename S,
typename T,
typename PT>
640typename ShadowClass<S, T, PyObjectPlus, PT>::TDerivedMakers* ShadowClass<S, T, PyObjectPlus, PT>::derivedMakers_ = 0;
659template <
typename ShadoweeType>
660using ShadoweePtr = std::conditional_t<std::is_const_v<ShadoweeType>,
661 typename impl::ShadowTraits<typename ShadoweeTraits<ShadoweeType>::TShadow>::TConstCppClassPtr,
662 typename impl::ShadowTraits<typename ShadoweeTraits<ShadoweeType>::TShadow>::TCppClassPtr
671#define PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectParent, t_PointerTraits) \
672 class dllInterface i_PyObjectShadowClass : \
673 public ::lass::python::ShadowClass< i_PyObjectShadowClass, t_CppClass, t_PyObjectParent, t_PointerTraits > \
675 PY_HEADER(t_PyObjectParent) \
676 static void _lassPyClassRegisterHook() { registerWithParent(); } \
678 i_PyObjectShadowClass(const TConstShadoweePtr& shadowee, ::lass::python::impl::ShadoweeConstness constness): \
679 ::lass::python::ShadowClass< i_PyObjectShadowClass, t_CppClass, t_PyObjectParent, t_PointerTraits >(shadowee, constness) \
687#define PY_SHADOW_CLASS_PTRTRAITS(dllInterface, i_PyObjectShadowClass, t_CppClass, pointerTraits)\
688 PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, ::lass::python::PyObjectPlus, pointerTraits < t_CppClass > )
692#define PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)\
693 PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, ::lass::python::PyObjectPlus, ::lass::python::SharedPointerTraits< t_CppClass >)
695#define PY_SHADOW_CLASS_DERIVED(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)\
696 PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent, t_PyObjectShadowParent::TPointerTraits::Rebind< t_CppClass >::Type )
701#define PY_SHADOW_CLASS_NOCONSTRUCTOR_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectBase, t_PyObjectParent)\
702 PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectBase, t_PyObjectParent)
707#define PY_SHADOW_CLASS_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass)\
708 PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)
713#define PY_WEAK_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)\
714 PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)
719#define PY_WEAK_SHADOW_CLASS_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass)\
720 PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)
725#define PY_SHADOW_CLASS_ENABLE_AUTOMATIC_INVALIDATION(i_PyObjectShadowClass)
730#define PY_SHADOW_CLASS_DERIVED_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)\
731 PY_SHADOW_CLASS_DERIVED(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)
738#define PY_SHADOW_CASTERS(t_ShadowObject)\
743 template <> struct ShadoweeTraits< t_ShadowObject::TShadowee >: ::lass::meta::True \
745 typedef t_ShadowObject TShadow; \
747 typedef t_ShadowObject::TPointerTraits TPointerTraits; \
758#define PY_SHADOW_DOWN_CASTERS(t_ShadowObject)\
759 PY_SHADOW_CASTERS(t_ShadowObject)
764#define PY_SHADOW_DOWN_CASTERS_NOCONSTRUCTOR(t_ShadowObject)\
765 PY_SHADOW_CASTERS(t_ShadowObject)
770#define PY_CLASS_CONVERTOR_EX( t_ShadowObject, v_conversionFunction, i_uniqueName )\
771 LASS_EXECUTE_BEFORE_MAIN_EX( LASS_CONCATENATE( lassPyClassConverter_, i_uniqueName ),\
772 lass::python::impl::ShadowTraits< t_ShadowObject >::addConverter( v_conversionFunction );\
775#define PY_CLASS_CONVERTOR( i_ShadowObject, t_sourceType )\
776 PY_CLASS_CONVERTOR_EX( i_ShadowObject, (::lass::python::impl::defaultConvertor< i_ShadowObject, t_sourceType >) , i_ShadowObject );
PyObjectPtr< PyObject >::Type TPyObjPtr
PyObjectPtr to a PyObject.
std::conditional_t< std::is_const_v< ShadoweeType >, typename impl::ShadowTraits< typename ShadoweeTraits< ShadoweeType >::TShadow >::TConstCppClassPtr, typename impl::ShadowTraits< typename ShadoweeTraits< ShadoweeType >::TShadow >::TCppClassPtr > ShadoweePtr
Helper to get the pointer type holding the shadowee in a shadow object.
lass::util::SharedPtr< T, PyObjectStorage, PyObjectCounter > fromNakedToSharedPtrCast(PyObject *object)
fromNakedToSharedPtrCast.
Comprehensive C++ to Python binding library.
Library for Assembled Shared Sources.