Library of Assembled Shared Sources
Python bindings

Detailed Description

Comprehensive C++ to Python binding library.

The lass::python namespace provides a comprehensive Python binding system that allows easy integration between C++ code and Python scripts. Lass Python bindings support both native Python-aware classes and shadow classes for existing C++ types.

Key Components:

Class Export Approaches:

  1. Native Python Classes: C++ classes that inherit from PyObjectPlus and are designed to be Python-compatible from the start
  2. Shadow Classes: Wrapper classes for existing C++ types using PY_SHADOW_CLASS macros - the shadow inherits from PyObjectPlus and wraps the original type

Binding Features:

Topics

 Class Definitions
 Defining Python classes from C++ with methods, properties, operators, and nested types.
 
 Enum Definitions
 Defining first-class enum types in Python from C++ enums.
 
 Python Exceptions
 Handling Python exceptions in C++, and translating C++ exceptions to Python.
 
 PyExportTraits
 Traits to convert between C++ and Python types.
 
 Module Definitions
 Defining Python modules from C++ with classes, functions, and enums.
 
 Python Iterators
 Exposing iterators to Python.
 
 Special Methods
 Predefined constants for Python special methods (magic methods) that can be used as method names in class export macros.
 

Data Structures

struct  lass::python::impl::ArgumentTraitsPyObject< util::SharedPtr< T, PyObjectStorage, PyObjectCounter > >
 by PyObjectPtr. More...
 
struct  lass::python::impl::ArgumentTraitsShadowee< util::SharedPtr< T, S, C > >
 by SharedPtr (T may be const). More...
 
struct  lass::python::ArgumentTraits< T >
 by copy. More...
 
struct  lass::python::ArgumentTraits< const T >
 by const copy. More...
 
struct  lass::python::ArgumentTraits< T * >
 by non-const pointer to non-const object. More...
 
struct  lass::python::ArgumentTraits< const T * >
 by non-const pointer to const object. More...
 
struct  lass::python::ArgumentTraits< T & >
 by reference to non-const object. More...
 
struct  lass::python::ArgumentTraits< const T & >
 by reference to const object. More...
 
struct  lass::python::ArgumentTraits< util::SharedPtr< T, S, C > >
 by SharedPtr More...
 
struct  lass::python::ArgumentTraits< const char * >
 by SharedPtr More...
 
class  lass::python::MaybeNone< T >
 Wrapper to type-hint return values in Python that maybe None but not likely. More...
 
class  lass::python::NoNone< T >
 Wrapper to prevent None values being passed to and from Python. More...
 
class  lass::python::PyObjectPlus
 PyObjectPlus. More...
 
struct  lass::python::IsPyObject< T >
 meta function to detect if a type is a PyObject-derived type More...
 
class  lass::python::PyObjectStorage< T, Cascade >
 Recommended storage policy for single PyObject objects, implementation of StoragePolicy concept. More...
 
class  lass::python::PyObjectCounter
 The recommended counter for the pyobject pointers, implementation of CounterPolicy concept. More...
 
struct  lass::python::PyObjectPtr< T >
 templated "typedef" to a python shared pointer More...
 
class  lass::python::Self< T >
 Wrapper to type-hint a return value as Self. More...
 

Macros

#define PY_MODULE_INTEGER_CONSTANTS(i_module, ...)
 Injects a number of constants into a Python module.
 
#define PY_HEADER(t_parentClass)
 Place as first line of your Pythonized class.
 
#define PY_SHADOW_CLASS_NOCONSTRUCTOR_EX(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectBase, t_PyObjectParent)
 
#define PY_SHADOW_CLASS_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass)
 
#define PY_WEAK_SHADOW_CLASS(dllInterface, i_PyObjectShadowClass, t_CppClass)
 
#define PY_WEAK_SHADOW_CLASS_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass)
 
#define PY_SHADOW_CLASS_ENABLE_AUTOMATIC_INVALIDATION(i_PyObjectShadowClass)
 
#define PY_SHADOW_CLASS_DERIVED_NOCONSTRUCTOR(dllInterface, i_PyObjectShadowClass, t_CppClass, t_PyObjectShadowParent)
 
#define PY_SHADOW_DOWN_CASTERS(t_ShadowObject)
 
#define PY_SHADOW_DOWN_CASTERS_NOCONSTRUCTOR(t_ShadowObject)
 

Typedefs

typedef PyObjectPtr< PyObject >::Type lass::python::TPyObjPtr
 PyObjectPtr to a PyObject.
 
template<typename ShadoweeType>
using lass::python::ShadoweePtr
 Helper to get the pointer type holding the shadowee in a shadow object.
 

Functions

template<class T>
lass::util::SharedPtr< T, PyObjectStorage, PyObjectCounterlass::python::fromNakedToSharedPtrCast (PyObject *object)
 fromNakedToSharedPtrCast.
 
template<class T>
PyObject * lass::python::fromSharedPtrToNakedCast (const util::SharedPtr< T, PyObjectStorage, PyObjectCounter > &object)
 fromSharedPtrToNakedCast.
 
template<typename Out, typename In>
Out lass::python::staticPyCast (const In &in)
 static_cast for python pointers
 
template<typename Out, typename In>
Out lass::python::dynamicPyCast (const In &in)
 dynamic_cast for python pointers
 
TPyObjPtr lass::python::getPyObjectByName (const std::string &iName)
 retrieve pointer to PyObject by its name in the script.
 
void lass::python::putenv (const std::string &key, const std::string &value)
 os.environ[key] = value
 
void lass::python::putenv (const char *key, const char *value)
 os.environ[key] = value
 

Module Entrypoint and Injection Macros

These macros handle module initialization, injection, and extension module creation.

They manage the Python module lifecycle from creation to registration with the Python interpreter.

If you're building a Python extension module (a .pyd or .so file), you will typically use the entrypoint macros to create the required PyInit_* function that Python calls:

// Declare module
PY_DECLARE_MODULE_NAME_DOC(mymodule, "mymodule", "My example module")
// Add functions and classes
// ...
// Create module entrypoint for Python extension
#define PY_MODULE_ENTRYPOINT(i_module)
Create a Python module initialization function using the module identifier as the function name.
#define PY_DECLARE_MODULE_NAME_DOC(i_module, s_name, s_doc)
Declare and define a ModuleDefinition object representing a Python module.

The injection macros are more low-level and can be used to create modules at runtime to be registered with an embedded Python interpreter.

#define PY_EXTENSION_MODULE_EX(i_module, f_injection, s_doc)
 Inject a python module so Python is aware of it and produce all necessary code so a module can be used as extension of Python.
 

Macro Definition Documentation

◆ PY_MODULE_INTEGER_CONSTANTS

#define PY_MODULE_INTEGER_CONSTANTS ( i_module,
... )
Value:
LASS_EXECUTE_BEFORE_MAIN_EX\
( LASS_CONCATENATE( lassExecutePyModuleIntegerConstants_, i_module),\
lass::python::impl::addIntegerConstantsToModule( i_module, #__VA_ARGS__, __VA_ARGS__); )

Injects a number of constants into a Python module.

The number of arguments to the macro is variable but is limited to the number specified during the build of lass. The name of the identifier in Python is the same as the one in C++. This makes export of enums more efficient.

An example is: enum Foo { the = 0x1, fan = 0x2, has = 0x5, started = 0x7 };

PY_MODULE_INTEGER_CONSTANTS( theFanModule, the, fan, has, started )

Parameters
i_modulethe identifier of a module declared by PY_DECLARE_MODULE
...the identifiers that will be injected

Definition at line 72 of file bulk_add.h.

◆ PY_EXTENSION_MODULE_EX

#define PY_EXTENSION_MODULE_EX ( i_module,
f_injection,
s_doc )
Value:
extern "C" __declspec(dllexport)\
void LASS_CONCATENATE(init, i_module) () {\
PY_INJECT_MODULE_EX(i_module, const_cast<char*>( LASS_STRINGIFY(i_module) ), s_doc);\
f_injection ();\
}

Inject a python module so Python is aware of it and produce all necessary code so a module can be used as extension of Python.

A limitation in comparison with embedded modules is that the name of the module cannot be changed anymore upon injection.

Parameters
i_modulethe identifier of a module declared by PY_DECLARE_MODULE
f_injectionthe function that will inject all the classes for this module
s_docdocumentation of module as shown in Python (zero terminated C string)

Definition at line 224 of file pyobject_macros.h.

◆ PY_HEADER

#define PY_HEADER ( t_parentClass)
Value:
public: \
typedef t_parentClass _lassPyParentType; \
static ::lass::python::impl::ClassDefinition _lassPyClassDef; \
::lass::python::impl::ClassDefinition* _lassPyGetClassDef() const override { return &_lassPyClassDef; } \
private:
Definition of a Python class.

Place as first line of your Pythonized class.


For t_parentClass use the C++ class from which you wish the python object inherits.
t_parentClass must also be a Pythonized class or use lass::python::PyObjectPlus as default.

Remarks
Any declarations coming after this macro are private!

Definition at line 57 of file pyobject_plus.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

Definition at line 701 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

Definition at line 707 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

Definition at line 713 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

Definition at line 719 of file pyshadow_object.h.

◆ PY_SHADOW_CLASS_ENABLE_AUTOMATIC_INVALIDATION

#define PY_SHADOW_CLASS_ENABLE_AUTOMATIC_INVALIDATION ( i_PyObjectShadowClass)
Deprecated

Definition at line 725 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

Definition at line 730 of file pyshadow_object.h.

◆ PY_SHADOW_DOWN_CASTERS

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

Definition at line 758 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

Definition at line 764 of file pyshadow_object.h.

Typedef Documentation

◆ TPyObjPtr

typedef PyObjectPtr<PyObject>::Type lass::python::TPyObjPtr

PyObjectPtr to a PyObject.

Due to historical reasons, the names PyObjectPtr and TPyObjPtr are a bit confusing: TPyObjPtr is a PyObjectPtr for PyObject, while PyObjectPtr is the general one.

Definition at line 252 of file pyobject_ptr.h.

◆ ShadoweePtr

template<typename ShadoweeType>
using lass::python::ShadoweePtr
Initial value:
std::conditional_t<std::is_const_v<ShadoweeType>,
typename impl::ShadowTraits<typename ShadoweeTraits<ShadoweeType>::TShadow>::TConstCppClassPtr,
typename impl::ShadowTraits<typename ShadoweeTraits<ShadoweeType>::TShadow>::TCppClassPtr
>

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

ShadoweeType is the C++ type being wrapped by a shadow object. This shadow object holds the wrapped shadowee in a pointer type. This pointer type is defined by the pointer traits passed to PY_SHADOW_CLASS_EX or PY_SHADOW_CLASS_PTRTRAITS. By default, this is SharedPointerTraits<ShadoweeType>.

This helper will directly give you the pointer type used to store the shadowee in the shadow objects. 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 derives from PyObjectPlus, then the pointer type PyObjectPtr<ShadoweeType>::Type

Definition at line 660 of file pyshadow_object.h.

Function Documentation

◆ fromNakedToSharedPtrCast()

template<class T>
lass::util::SharedPtr< T, PyObjectStorage, PyObjectCounter > lass::python::fromNakedToSharedPtrCast ( PyObject * object)

fromNakedToSharedPtrCast.

Helper function casting a PyObject coming from the Python interface to a SharedPtr object for use in C++. Reference counts are taken care of (it's icremented by one).

Definition at line 263 of file pyobject_ptr.h.

Referenced by lass::python::impl::ClassDefinition::establishMagicalBackLinks, and getPyObjectByName().

◆ fromSharedPtrToNakedCast()

template<class T>
PyObject * lass::python::fromSharedPtrToNakedCast ( const util::SharedPtr< T, PyObjectStorage, PyObjectCounter > & object)

fromSharedPtrToNakedCast.

Helper function casting an object used in C++ for use in Python. The key operation done here is to take care of the reference counting. Failing to use this function may yield unexpected reference count.

Definition at line 280 of file pyobject_ptr.h.

Referenced by lass::python::impl::construct(), lass::python::IntEnumDefinition< EnumType >::doFreezeDefinition(), lass::python::EnumDefinition< EnumType, ValueType >::freezeEnumerators(), and lass::python::impl::handleException().

◆ getPyObjectByName()

LASS_PYTHON_DLL TPyObjPtr LASS_CALL lass::python::getPyObjectByName ( const std::string & iName)

retrieve pointer to PyObject by its name in the script.

Returns
new reference to PyObject iName or NULL if iName does not exist (without setting an exception!)

Definition at line 71 of file utilities.cpp.

References fromNakedToSharedPtrCast(), and PY_ENFORCE_POINTER.