Library of Assembled Shared Sources
 
Loading...
Searching...
No Matches
Python Shadow Classes

Detailed Description

Export C++ classes that don't derive from lass::python::PyObjectPlus.

Shadow classes are LASS' wrapper classes that allow you to export C++ classes that don't derive from lass::python::PyObjectPlus to Python.

They are defined by invoking two macros:

Both macros are typically invoked in a header file (not necessarily the one that defines the original C++ classes), as both macros must be seen by all exports that use this class as parameter or return type.

Once you have defined the Shadow class, you use the regular macros like PY_DECLARE_CLASS_NAME or PY_CLASS_METHOD to fully define the Python export for this class. But instead of using the C++ class as first argument, you use the shadow class.

Here's a quick comparison between both techniques:

// Direct Python class | // Shadow Python class
|
// spam.h | // spam.h
|
class Spam: public lass::python::PyObjectPlus | class Spam
{ | {
public: | public:
void method(int a, int b); | void method(int a, int b);
}; | };
|
class Ham: public Spam | class Ham: public Spam
{ | {
PY_HEADER(Spam) |
public: | public:
void other(int c); | void other(int c);
}; | };
|
| PY_SHADOW_CLASS(LASS_DLL_EXPORT, PySpam, Spam)
|
| PY_SHADOW_CLASS_DERIVED(LASS_DLL_EXPORT, PyHam, Ham, PySpam)
|
// spam.cpp | // spam.cpp
|
PY_DECLARE_CLASS(Spam) | PY_DECLARE_CLASS_NAME(PySpam, "Spam")
PY_CLASS_METHOD(Spam, method) | PY_CLASS_METHOD(PySpam, method)
|
PY_CLASS_METHOD(Ham, other) | PY_CLASS_METHOD(PyHam, other)
#define PY_DECLARE_CLASS(i_cppClass)
Declare a Python class with automatic name and no documentation.
#define PY_DECLARE_CLASS_NAME(t_cppClass, s_name)
Declare a Python class with custom name but no documentation.
#define PY_CLASS_METHOD(i_cppClass, i_cppMethod)
Export a C++ method to Python.
#define PY_HEADER(t_parentClass)
Place as first line of your Pythonized class.
#define PY_SHADOW_CLASS_DERIVED(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)
Declare Python shadow child class with a parent.
#define PY_SHADOW_CASTERS(t_ShadowObject)
Define lass::python::ShadoweeTraits for shadow class.
#define PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)
Declare Python shadow class with util::SharedPtr as default shadowee pointer type.
Pointer-traits

Shadow-classes need a pointer type to store their shadowee instances. This is defined by the pointer traits chosen for the shadow class.

By default, the SharedPointerTraits is used with util::SharedPtr as shadowee pointer, but you can specify a custom one using PY_SHADOW_CLASS_PTRTRAITS.

Available pointer traits are:

To make your custom pointer traits, copy the pattern of these three.

Note
id must return an ID that uniquely identifies a shadowee instance for as long as it is alive and at least one shadow pointer references it (when it's removed from the shadow cache). Return 0 to opt-out from the shadow cache.

Classes

struct  lass::python::SharedPointerTraits< T, S, C >
 Pointer-traits for Python Shadow classes that use lass::util::SharedPtr for storage. More...
 
struct  lass::python::NakedPointerTraits< T >
 Pointer-traits for Python Shadow classes that use raw * pointers for storage. More...
 
struct  lass::python::StdSharedPointerTraits< T >
 Pointer-traits for Python Shadow classes that use std::shared_ptr for storage. More...
 

Macros

#define PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectParent, t_PointerTraits)
 Declare Python shadow class with full control.
 
#define PY_SHADOW_CLASS_PTRTRAITS(dllInterface, i_PyObjectShadowClass, t_CppClass, pointerTraits)
 Declare Python shadow class with custom pointer traits.
 
#define PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)
 Declare Python shadow class with util::SharedPtr as default shadowee pointer type.
 
#define PY_SHADOW_CLASS_DERIVED(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)
 Declare Python shadow child class with a parent.
 
#define PY_SHADOW_CLASS_NOCONSTRUCTOR_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectBase, t_PyObjectParent)
 Deprecated alias for PY_SHADOW_CLASS_EX.
 
#define PY_SHADOW_CLASS_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass)
 Deprecated alias for PY_SHADOW_CLASS.
 
#define PY_WEAK_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)
 Deprecated alias for PY_SHADOW_CLASS.
 
#define PY_WEAK_SHADOW_CLASS_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass)
 Deprecated alias for PY_SHADOW_CLASS.
 
#define PY_SHADOW_CLASS_ENABLE_AUTOMATIC_INVALIDATION(i_PyObjectShadowClass)
 Deprecated.
 
#define PY_SHADOW_CLASS_DERIVED_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)
 Deprecated alias for PY_SHADOW_CLASS_DERIVED.
 
#define PY_SHADOW_CASTERS(t_ShadowObject)
 Define lass::python::ShadoweeTraits for shadow class.
 
#define PY_SHADOW_DOWN_CASTERS(t_ShadowObject)
 Deprecated alias for PY_SHADOW_CASTERS.
 
#define PY_SHADOW_DOWN_CASTERS_NOCONSTRUCTOR(t_ShadowObject)
 Deprecated alias for PY_SHADOW_CASTERS.
 
#define PY_CLASS_CONVERTOR_EX(t_ShadowObject, f_conversionFunction, i_uniqueName)
 Add implicit conversion function to Python class.
 
#define PY_CLASS_CONVERTOR(i_ShadowObject, t_sourceType)
 Add implicit auto-conversion to Python class.
 

Typedefs

using lass::python::TShadoweeID = num::TuintPtr
 ID-type to uniquely identify shadowee instances in the shadow cache.
 
template<typename ShadoweeType>
using lass::python::ShadoweePtr
 Helper to get the pointer type holding the shadowee in a shadow object.
 

Macro Definition Documentation

◆ PY_SHADOW_CLASS_EX

#define PY_SHADOW_CLASS_EX ( dllInterface,
i_PyObjectShadowClass,
t_CppClass,
t_PyObjectParent,
t_PointerTraits )

Declare Python shadow class with full control.

Parameters
dllInterfacedesired DLL-interface of shadow class
i_PyObjectShadowClassUnique C++ class identifier (unqualified name) of shadow class
t_CppClasstypename of the shadowee, the native C++ class being shadowed
t_PyObjectParentthe shadow's class parent (either another shadow class or lass::python::PyObjectPlus), this will be the base class of the Python type.
t_PointerTraitscomplete type of pointer-traits to be used for shadowee storage.

Definition at line 845 of file pyshadow_object.h.

◆ PY_SHADOW_CLASS_PTRTRAITS

#define PY_SHADOW_CLASS_PTRTRAITS ( dllInterface,
i_PyObjectShadowClass,
t_CppClass,
pointerTraits )
Value:
PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, ::lass::python::PyObjectPlus, pointerTraits < t_CppClass > )
#define PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectParent, t_PointerTraits)
Declare Python shadow class with full control.

Declare Python shadow class with custom pointer traits.

The pointer-traits define how shadowee classes will be stored as pointer in the shadow class. Only specify the pointer-traits template name, the macro will add t_CppClass as template argument.

Parameters
dllInterfacedesired DLL-interface of shadow class
i_PyObjectShadowClassUnique C++ class identifier (unqualified name) of shadow class
t_CppClasstypename of the shadowee, the native C++ class being shadowed
pointerTraitsshadowee pointer-traits template name

Definition at line 870 of file pyshadow_object.h.

◆ PY_SHADOW_CLASS

#define PY_SHADOW_CLASS ( dllInterface,
i_PyObjectShadowClass,
t_CppClass )
Value:
Pointer-traits for Python Shadow classes that use lass::util::SharedPtr for storage.

Declare Python shadow class with util::SharedPtr as default shadowee pointer type.

Parameters
dllInterfacedesired DLL-interface of shadow class
i_PyObjectShadowClassUnique C++ class identifier (unqualified name) of shadow class
t_CppClasstypename of the shadowee, the native C++ class being shadowed

Definition at line 880 of file pyshadow_object.h.

◆ PY_SHADOW_CLASS_DERIVED

#define PY_SHADOW_CLASS_DERIVED ( dllInterface,
i_PyObjectShadowClass,
t_CppClass,
t_PyObjectShadowParent )
Value:
PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent, t_PyObjectShadowParent::TPointerTraits::Rebind< t_CppClass >::Type )

Declare Python shadow child class with a parent.

Register a derived shadow class to reflect the same polymorphic class hierarchy in Python as in C++. If Ham derives from Spam, then a SharedPtr<Spam> pointer that contains a Ham instance will properly be returned as a Ham object in Python.

Derived shadow classes use the same pointer traits as the parent class, so you don't need to specify it again.

Parameters
dllInterfacedesired DLL-interface of shadow class
i_PyObjectShadowClassUnique C++ class identifier (unqualified name) of shadow class
t_CppClasstypename of the shadowee, the native C++ class being shadowed
t_PyObjectShadowParentthe parent's shadow class, this will be the base class of the Python type.

Definition at line 898 of file pyshadow_object.h.

◆ PY_SHADOW_CLASS_NOCONSTRUCTOR_EX

#define PY_SHADOW_CLASS_NOCONSTRUCTOR_EX ( dllInterface,
i_PyObjectShadowClass,
t_CppClass,
t_PyObjectBase,
t_PyObjectParent )
Value:
PY_SHADOW_CLASS_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectBase, t_PyObjectParent)

Deprecated alias for PY_SHADOW_CLASS_EX.

Deprecated
Use PY_SHADOW_CLASS_EX instead, it's a direct 1:1 replacement

Definition at line 905 of file pyshadow_object.h.

◆ PY_SHADOW_CLASS_NOCONSTRUCTOR

#define PY_SHADOW_CLASS_NOCONSTRUCTOR ( dllInterface,
i_PyObjectShadowClass,
t_CppClass )
Value:
PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)

Deprecated alias for PY_SHADOW_CLASS.

Deprecated
Use PY_SHADOW_CLASS instead, it's a direct 1:1 replacement

Definition at line 912 of file pyshadow_object.h.

◆ PY_WEAK_SHADOW_CLASS

#define PY_WEAK_SHADOW_CLASS ( dllInterface,
i_PyObjectShadowClass,
t_CppClass )
Value:
PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)

Deprecated alias for PY_SHADOW_CLASS.

Deprecated
Use PY_SHADOW_CLASS instead, it's a direct 1:1 replacement

Definition at line 919 of file pyshadow_object.h.

◆ PY_WEAK_SHADOW_CLASS_NOCONSTRUCTOR

#define PY_WEAK_SHADOW_CLASS_NOCONSTRUCTOR ( dllInterface,
i_PyObjectShadowClass,
t_CppClass )
Value:
PY_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)

Deprecated alias for PY_SHADOW_CLASS.

Deprecated
Use PY_SHADOW_CLASS instead, it's a direct 1:1 replacement

Definition at line 926 of file pyshadow_object.h.

◆ PY_SHADOW_CLASS_ENABLE_AUTOMATIC_INVALIDATION

#define PY_SHADOW_CLASS_ENABLE_AUTOMATIC_INVALIDATION ( i_PyObjectShadowClass)

Deprecated.

Deprecated
This call has no effect and can be removed

Definition at line 933 of file pyshadow_object.h.

◆ PY_SHADOW_CLASS_DERIVED_NOCONSTRUCTOR

#define PY_SHADOW_CLASS_DERIVED_NOCONSTRUCTOR ( dllInterface,
i_PyObjectShadowClass,
t_CppClass,
t_PyObjectShadowParent )
Value:
PY_SHADOW_CLASS_DERIVED(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)

Deprecated alias for PY_SHADOW_CLASS_DERIVED.

Deprecated
Use PY_SHADOW_CLASS_DERIVED instead, it's a direct 1:1 replacement

Definition at line 939 of file pyshadow_object.h.

◆ PY_SHADOW_CASTERS

#define PY_SHADOW_CASTERS ( t_ShadowObject)

Define lass::python::ShadoweeTraits for shadow class.

This ensures that shadowee class becomes usable as parameter or return type. If PySpam is t_ShadowObject, the shadow class of Spam, then Spam, const Spam&, Spam*, lass::util::SharedPtr<Spam>, etc. all become usable as parameter or return types.

Parameters
t_ShadowObjectfully qualified typename of Python Shadow class
Note
This macro MUST be invoked in the global namespace
This macro MUST be invoked in the same header that declares the shadow class with PY_SHADOW_CLASS or similar. Every translation unit that uses the shadow class must include it.

Definition at line 961 of file pyshadow_object.h.

◆ PY_SHADOW_DOWN_CASTERS

#define PY_SHADOW_DOWN_CASTERS ( t_ShadowObject)
Value:
PY_SHADOW_CASTERS(t_ShadowObject)

Deprecated alias for PY_SHADOW_CASTERS.

Deprecated
Use PY_SHADOW_CASTERS instead, it's a direct 1:1 replacement

Definition at line 982 of file pyshadow_object.h.

◆ PY_SHADOW_DOWN_CASTERS_NOCONSTRUCTOR

#define PY_SHADOW_DOWN_CASTERS_NOCONSTRUCTOR ( t_ShadowObject)
Value:
PY_SHADOW_CASTERS(t_ShadowObject)

Deprecated alias for PY_SHADOW_CASTERS.

Deprecated
Use PY_SHADOW_CASTERS instead, it's a direct 1:1 replacement

Definition at line 989 of file pyshadow_object.h.

◆ PY_CLASS_CONVERTOR_EX

#define PY_CLASS_CONVERTOR_EX ( t_ShadowObject,
f_conversionFunction,
i_uniqueName )
Value:
LASS_EXECUTE_BEFORE_MAIN_EX( LASS_CONCATENATE( lassPyClassConverter_, i_uniqueName ),\
lass::python::impl::ShadowTraits< t_ShadowObject >::addConverter( f_conversionFunction );\
)

Add implicit conversion function to Python class.

Add a conversion function to a Python class to implicitly convert a Python object to the C++ class when it is being passed as a parameter to a C++ function

By default, you need to convert types by explicitly constructing an object in Python, or you must overload the function on different types. By adding implicit convertors, they will automatically be attempted when calling functions taking the native C++ class. If conversion is successful, the function is called.

The conversion function must be of the following signature: int f(PyObject* obj, ShadoweePtr<T>& val). It receives a pointer to the Python object for which the conversion must be attempted. If successful, you should construct a new instance on the heap of the native C++ class, assign it to the shadowee pointer, and return 0. If failed, you should return 1, and a generic TypeError will be set.

Conversions are attempted in the order of registration.

This macro must be invoked in the same translation unit (.cpp file) as `PY_DECLARE_CLASS_`.

Parameters
t_ShadowObjectPython class (fully qualified) on which to add the convertor
f_conversionFunctionconversion function
i_uniqueNameidentifier used to name the generated registration hook
Example:
class Spam
{
public:
Spam(const std::string& s);
};
int spamConversion(PyObject* obj, lass::python::ShadoweePtr<Spam>& spam)
{
std::string s;
if (::lass::python::pyGetSimpleObject(obj, s) == 0)
{
spam.reset(new Spam(s));
return 0; // conversion succeeded
}
return 1; // conversion failed
}
PY_SHADOW_CLASS(LASS_DLL_EXPORT, PySpam, Spam)
PY_DECLARE_CLASS_NAME(PySpam, "Spam")
PY_CLASS_CONSTRUCTOR_1(PySpam, const std::string&)
PY_CLASS_CONVERTOR_EX(PySpam, spamConversion, spam)
void func(const Spam& spam);
PY_MODULE_CLASS(mod, PySpam)
#define PY_CLASS_CONSTRUCTOR_1(i_cppClass, t_P1)
Export C++ constructor as Python class constructor with 1 parameters.
#define PY_MODULE_CLASS(i_module, t_cppClass)
Add a Python class to a module.
#define PY_MODULE_FUNCTION(i_module, f_cppFunction)
Export a C++ function to Python.
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.
#define PY_CLASS_CONVERTOR_EX(t_ShadowObject, f_conversionFunction, i_uniqueName)
Add implicit conversion function to Python class.
mod.func(mod.Spam("abc")) # explicit conversion using constructor
mod.func("abc") # implicit conversion using convertor
See also
PY_CLASS_CONVERTOR for adding auto-convertors using the constructor

Definition at line 1055 of file pyshadow_object.h.

◆ PY_CLASS_CONVERTOR

#define PY_CLASS_CONVERTOR ( i_ShadowObject,
t_sourceType )
Value:
PY_CLASS_CONVERTOR_EX( i_ShadowObject, (::lass::python::impl::defaultConvertor< i_ShadowObject, t_sourceType >) , i_ShadowObject );

Add implicit auto-conversion to Python class.

Add an implicit convertor from t_sourceType to the Python class i_ShadowObject. It is attempted when a Python object that is not already an instance of that class is passed to a C++ function taking the C++ class as a parameter: the object is first converted to an instance of t_sourceType, from which a new instance of the C++ class is constructed. This assumes the C++ class has a matching constructor.

Without it, you must convert the value explicitly in Python by constructing an instance of the Python class, or the C++ function must be overloaded on t_sourceType.

Conversions are attempted in the order of registration.

This macro must be invoked in the same translation unit (.cpp file) as `PY_DECLARE_CLASS_`.

Parameters
i_ShadowObjectPython class identifier (unqualified) on which to add the auto-convertor
t_sourceTypetype from which to convert. It must be default-constructible and be exported to Python as a class or with PyExportTraits.
Example:
class Spam
{
public:
Spam(const std::string& s);
};
PY_SHADOW_CLASS(LASS_DLL_EXPORT, PySpam, Spam)
PY_DECLARE_CLASS_NAME(PySpam, "Spam")
PY_CLASS_CONSTRUCTOR_1(PySpam, const std::string&)
PY_CLASS_CONVERTOR(PySpam, std::string)
void func(const Spam& spam);
PY_MODULE_CLASS(mod, PySpam)
#define PY_CLASS_CONVERTOR(i_ShadowObject, t_sourceType)
Add implicit auto-conversion to Python class.
mod.func(mod.Spam("abc")) # explicit conversion using constructor
mod.func("abc") # implicit conversion using convertor
See also
PY_CLASS_CONVERTOR_EX for adding convertors with custom conversion functions

Definition at line 1107 of file pyshadow_object.h.

Typedef Documentation

◆ ShadoweePtr

template<typename ShadoweeType>
using lass::python::ShadoweePtr

Helper to get the pointer type holding the shadowee in a shadow object.

Template Parameters
ShadoweeTypenative C++ class, either the shadowee type being wrapped by a shadow class, or a direct exported type that derives from lass::python::PyObjectPlus.

This helper gives you the correct pointer type to store a C++ class on the heap (either a shadowee type, or a direct Python class) that is compatible with the defined Python exports

If ShadoweeType is a shadowee type, this will be the pointer type that holds the shadowee object in the shadow object, and it's defined by the pointer traits passed to PY_SHADOW_CLASS_EX() or PY_SHADOW_CLASS_PTRTRAITS() (or SharedPointerTraits<ShadoweeType> if you use the default PY_SHADOW_CLASS() ). Depending on the constness of the shadowee, you will either get a pointer to a non-const ShadoweeType or a pointer to a const ShadoweeType.

If ShadoweeType is not a shadowed type, but is instead a direct export and derives directly or indirectly from lass::python::PyObjectPlus, then the pointer type is simply lass::python::PyObjectPtr<ShadoweeType>::Type.

Definition at line 826 of file pyshadow_object.h.