HPy Types and Modules

Types, modules and their attributes (i.e. methods, members, slots, get-set descriptors) are defined in a similar way. Section HPy Type documents the type-specific and HPy Module documents the module-specific part. Section HPy Definition documents how to define attributes for both, types and modules.

HPy Type

Definition

struct HPyType_Spec
[source]
const char *name
[source]

The Python name of type (UTF-8 encoded)

int basicsize
[source]

The size in bytes of the types associated native structure. Usually, you define some C structure, e.g., typedef struct { int a; } MyObject;, and then this field is set to sizeof(MyObject).

int itemsize
[source]

The size of embedded elements (currently not supported).

unsigned long flags
[source]

Type flags (see HPy_TPFLAGS_DEFAULT, HPy_TPFLAGS_BASETYPE, HPy_TPFLAGS_HAVE_GC, and others if available).

HPyType_BuiltinShape builtin_shape
[source]

The internal shape of the type. The shape gives the necessary hint to compute the offset to the data pointer of the object’s underlying struct that should be returned when calling MyObject_AsStruct. ATTENTION: It is also necessary to specify the right base class in the type’s specification parameters (see HPyType_SpecParam). Assuming that the type’s C structure is called MyObject, this field should be initialized with .builtin_shape = SHAPE(MyObject). Note: This requires that you use HPyType_HELPERS or HPyType_LEGACY_HELPERS. Some more explanation: It would be possible to reduce this information to a Boolean that specifies if the type is a legacy type or not. Everything else could be determined by looking at the base classes. However, with this information it is possible to do the data pointer computation statically and thus is performance critical. Types that do not define a struct of their own, should set the value of .builtin_shape to the same value as the type they inherit from. If they inherit from a built-in type, they must set the corresponding .builtin_shape.

void *legacy_slots
[source]

Pointer to a NULL-terminated array of legacy (i.e. PyType_Slot) slots. A type with .legacy_slots != NULL is required to have HPyType_BuiltinShape_Legacy and to include PyObject_HEAD at the start of its struct. It would be easy to relax this requirement on CPython (where the PyObject_HEAD fields are always present) but a large burden on other implementations (e.g. PyPy, GraalPy) where a struct starting with PyObject_HEAD might not exist.

int **defines
[source]

Pointer to a NULL-terminated array of pointers to HPy defines (i.e. HPyDef *).

const char *doc
[source]

Docstring of the type (UTF-8 encoded; may be NULL)

enum HPyType_BuiltinShape
[source]
enumerator HPyType_BuiltinShape_Legacy = -1
[source]

A type whose struct starts with PyObject_HEAD or equivalent is a legacy type. A legacy type must set .builtin_shape = HPyType_BuiltinShape_Legacy in its HPyType_Spec. A type is a non-legacy type, also called HPy pure type, if its struct does not include PyObject_HEAD. Using pure types should be preferred. Legacy types are available to allow gradual porting of existing CPython extensions. A type with .legacy_slots != NULL (see HPyType_Spec.legacy_slots) is required to have HPyType_BuiltinShape_Legacy and to include PyObject_HEAD at the start of its struct. It would be easy to relax this requirement on CPython (where the PyObject_HEAD fields are always present) but a large burden on other implementations (e.g. PyPy, GraalPy) where a struct starting with PyObject_HEAD might not exist. Types created via the old Python C API are automatically legacy types.

enumerator HPyType_BuiltinShape_Object = 0
[source]

The type inherits from built-in type object (default).

enumerator HPyType_BuiltinShape_Type = 1
[source]

The type inherits from built-in type type. This can be used to create metaclasses. If using this shape, you need to specify base class ctx->h_TypeType.

enumerator HPyType_BuiltinShape_Long = 2
[source]

The type inherits from built-in type int (aka. long object). If using this shape, you need to specify base class ctx->h_LongType.

enumerator HPyType_BuiltinShape_Float = 3
[source]

The type inherits from built-in type float. If using this shape, you need to specify base class ctx->h_FloatType.

enumerator HPyType_BuiltinShape_Unicode = 4
[source]

The type inherits from built-in type str (aka. unicode object). If using this shape, you need to specify base class ctx->h_UnicodeType.

enumerator HPyType_BuiltinShape_Tuple = 5
[source]

The type inherits from built-in type tuple. If using this shape, you need to specify base class ctx->h_TupleType.

enumerator HPyType_BuiltinShape_List = 6
[source]

The type inherits from built-in type list. If using this shape, you need to specify base class ctx->h_ListType.

struct HPyType_SpecParam
[source]
HPyType_SpecParam_Kind kind
[source]

The kind of the type spec param.

int object
[source]

The value of the type spec param (an HPy handle).

enum HPyType_SpecParam_Kind
[source]
enumerator HPyType_SpecParam_Base = 1
[source]

Specify a base class. This parameter may be repeated but cannot be used together with HPyType_SpecParam_Kind.HPyType_SpecParam_BasesTuple.

enumerator HPyType_SpecParam_BasesTuple = 2
[source]

Specify a tuple of base classes. Cannot be used together with HPyType_SpecParam_Kind.HPyType_SpecParam_Base

enumerator HPyType_SpecParam_Metaclass = 3
[source]

Specify a meta class for the type.

HPyType_HELPERS()
[source]

A macro for creating (static inline) helper functions for custom types.

Two versions of the helper exist. One for legacy types and one for pure HPy types.

Example for a pure HPy custom type:

HPyType_HELPERS(PointObject)

It is also possible to inherit from some built-in types. The list of available built-in base types is given in enum HPyTupe_BuiltinShape. In case you want to inherit from one of those, it is necessary to specify the base built-in type in the HPyType_HELPERS macro. Here is an example for a pure HPy custom type inheriting from a built-in type ‘tuple’:

HPyType_HELPERS(PointObject, HPyType_BuiltinShape_Tuple)

This would generate the following:

  • PointObject * PointObject_AsStruct(HPyContext *ctx, HPy h): a static inline function that uses HPy_AsStruct to return the PointObject struct associated with a given handle. The behaviour is undefined if h is associated with an object that is not an instance of PointObject. However, debug mode will catch an incorrect usage.

  • SHAPE(PointObject): a macro that is meant to be used as static initializer in the corresponding HPyType_Spec. It is recommended to write .builtin_shape = SHAPE(PointObject) such that you don’t have to remember to update the spec when the helpers used changes.

Example for a legacy custom type:

HPyType_LEGACY_HELPERS(PointObject)

This would generate the same functions and constants as above, except:

  • _HPy_AsStruct_Legacy is used instead of _HPy_AsStruct_Object.

  • SHAPE(PointObject) would be HPyType_BuiltinShape_Legacy.

Parameters
HPyType_LEGACY_HELPERS(TYPE)
[source]

Convenience macro which is equivalent to: HPyType_HELPERS(TYPE, HPyType_BuiltinShape_Legacy)

HPy_TPFLAGS_DEFAULT
[source]

Default type flags for HPy types.

HPy_TPFLAGS_BASETYPE
[source]

Set if the type allows subclassing

HPy_TPFLAGS_HAVE_GC
[source]

If set, the object will be tracked by CPython’s GC. Probably irrelevant for GC-based alternative implementations.

Construction and More

HPy HPyType_FromSpec(HPyContext *ctx, HPyType_Spec *spec, HPyType_SpecParam *params)
[source]

Create a type from a HPyType_Spec and an additional list of specification parameters.

Parameters
  • ctx – The execution context.

  • spec – The type spec to use to create the type.

  • params – A 0-terminated list of type specification parameters or NULL.

Returns

a handle of the created type on success, HPy_NULL on failure.

const char *HPyType_GetName(HPyContext *ctx, HPy type)
[source]

Return the type’s name.

Equivalent to getting the type’s __name__ attribute. If you want to retrieve the type’s name as a handle that refers to a str, then just use HPy_GetAttr_s(ctx, type, "__name__").

Parameters
  • ctx – The execution context.

  • type – A Python type object. This argument must not be HPy_NULL and must be a type (i.e. it must inherit from Python type). If this is not the case, the behavior is undefined (verification of the argument is only done in debug mode).

Returns

The name of the type as C string (UTF-8 encoded) or NULL in case of an error. The returned pointer is read-only and guaranteed to be valid as long as the handle type is valid.

int HPyType_IsSubtype(HPyContext *ctx, HPy sub, HPy type)
[source]

Checks if sub is a subtype of type.

This function only checks for actual subtypes, which means that __subclasscheck__() is not called on type.

Parameters
  • ctx – The execution context.

  • sub – A Python type object. This argument must not be HPy_NULL and must be a type (i.e. it must inherit from Python type). If this is not the case, the behavior is undefined (verification of the argument is only done in debug mode).

  • type – A Python type object. This argument must not be HPy_NULL and must be a type (i.e. it must inherit from Python type). If this is not the case, the behavior is undefined (verification of the argument is only done in debug mode).

Returns

Non-zero if sub is a subtype of type.

HPy Module

HPY_EMBEDDED_MODULES

If HPY_EMBEDDED_MODULES is defined, this means that there will be several embedded HPy modules (and so, several HPy_MODINIT usages) in the same binary. In this case, some restrictions apply:

  1. all of the module’s methods/member/slots/… must be defined in the same file

  2. the embedder MUST declare the module to be embeddable by using macro HPY_MOD_EMBEDDABLE.

HPY_MOD_EMBEDDABLE(modname)
[source]

Declares a module to be embeddable which means that it and its members can be compiled/linked into a binary together with other embeddable HPy modules.

You may declare a module to be embeddable if all of its member definitions are in the same file.

struct HPyModuleDef
[source]

Definition of a Python module. Pointer to this struct is returned from the HPy initialization function HPyInit_{extname} and the Python interpreter creates a Python module from it. HPy supports only the multi-phase module initialization approach (PEP 451).

There is no HPy API to create a Python module manually, i.e., equivalent of PyModule_Create or PyModule_FromDefAndSpec, for the time being, but may be added if a use-case arises.

Note: unlike Python/C API, HPy module definition does not specify module name. The name if always taken from the ModuleSpec, which is also the case in multi-phase module initialization on Python/C API.

const char *doc
[source]

Docstring of the type (UTF-8 encoded; may be NULL)

int size
[source]

The size (in bytes) of the module state structure. If set to zero, then the module will not get allocated and assigned any HPy module state. Negative size, unlike in Python/C API, does not have any specific meaning and will produce a runtime error.

int *legacy_methods
[source]

NULL-terminated list of legacy module-level methods. In order to enable incremental migration from C API to HPy, it is possible to still add legacy method definitions. Those methods have a C API signature which means that they still receive PyObject * and similar arguments. If legacy methods are defined, you cannot create a universal binary (i.e. a binary that will run on all Python engines).

int **defines
[source]

Pointer to a NULL-terminated array of pointers to HPy defines (i.e. HPyDef *). Note, that some kinds of HPy definitions don’t make sense for a module. In particular, anything else than methods.

int **globals
[source]

Pointer to a NULL-terminated array of pointers to HPyGlobal variables. For details, see HPyGlobal.

HPy_MODINIT(ext_name, mod_def)
[source]

Convenience macro for generating the module initialization code. This will generate three functions that are used by to verify an initialize the module when loading:

get_required_hpy_major_version_<modname>

The HPy major version this module was built with.

get_required_hpy_minor_version_<modname>

The HPy minor version this module was built with.

HPyModuleDef* HPyInit_<extname>

The init function that will be called by the interpreter. This function does not have an access to HPyContext and thus cannot call any HPy APIs. The purpose of this function is to return a pointer to a HPyModuleDef structure that will serve as a specification of the module that should be created by the interpreter. HPy supports only multi-phase module initialization (PEP 451). Any module initialization code can be added to the HPy_mod_exec slot of the module if needed.

Example:

HPy_MODINIT(myextension_shared_library_filename, my_hpy_module_def)

HPy Definition

Defining slots, methods, members, and get-set descriptors for types and modules is done with HPy definition (represented by C struct HPyDef).

struct HPyDef
[source]

Generic structure of an HPy definition.

This struct can be used to define a slot, method, member, or get/set descriptor. For details, see embedded structures HPySlot, HPyMeth, HPyMember, or HPyGetSet.

HPyDef_Kind kind
[source]

The kind of this definition. The value of this field determines which one of the embedded members slot, meth, member, or getset is used. Since those are combined in a union, only one can be used at a time.

enum HPyDef_Kind
[source]

Enum to identify an HPy definition’s kind.

enumerator HPyDef_Kind_Slot
[source]
enumerator HPyDef_Kind_Meth
[source]
enumerator HPyDef_Kind_Member
[source]
enumerator HPyDef_Kind_GetSet
[source]
struct HPySlot
[source]

C structure to define an HPy slot.

It is perfectly fine to fill this structure manually. However, the recommended and easier way is to use macro HPyDef_SLOT.

int slot
[source]

The slot to fill.

HPyCFunction impl
[source]

Function pointer to the slot’s implementation

int cpy_trampoline
[source]

Function pointer to the CPython trampoline function which is used by CPython to call the actual HPy function impl.

struct HPyMeth
[source]

C structure to define an HPy method.

It is perfectly fine to fill this structure manually. However, the recommended and easier way is to use macro HPyDef_METH.

const char *name
[source]

The name of Python attribute (UTF-8 encoded)

HPyCFunction impl
[source]

Function pointer of the C function implementation

int cpy_trampoline
[source]

Function pointer to the CPython trampoline function which is used by CPython to call the actual HPy function impl.

int signature
[source]

Indicates the C function’s expected signature

const char *doc
[source]

Docstring of the method (UTF-8 encoded; may be NULL)

enum HPyMember_FieldType
[source]

Describes the type (and therefore also the size) of an HPy member.

enumerator HPyMember_SHORT
[source]
enumerator HPyMember_INT
[source]
enumerator HPyMember_LONG
[source]
enumerator HPyMember_FLOAT
[source]
enumerator HPyMember_DOUBLE
[source]
enumerator HPyMember_STRING
[source]
enumerator HPyMember_OBJECT
[source]
enumerator HPyMember_CHAR
[source]
enumerator HPyMember_BYTE
[source]
enumerator HPyMember_UBYTE
[source]
enumerator HPyMember_USHORT
[source]
enumerator HPyMember_UINT
[source]
enumerator HPyMember_ULONG
[source]
enumerator HPyMember_STRING_INPLACE
[source]
enumerator HPyMember_BOOL
[source]
enumerator HPyMember_OBJECT_EX
[source]
enumerator HPyMember_LONGLONG
[source]
enumerator HPyMember_ULONGLONG
[source]
enumerator HPyMember_HPYSSIZET
[source]
enumerator HPyMember_NONE
[source]
struct HPyMember
[source]

C structure to define an HPy member.

It is perfectly fine to fill this structure manually. However, the recommended and easier way is to use macro HPyDef_MEMBER.

const char *name
[source]

The name of Python attribute (UTF-8 encoded)

HPyMember_FieldType type
[source]

The type of the HPy member (see enum HPyMember_FieldType).

int offset
[source]

The location (byte offset) of the member. Usually computed with offsetof(type, field).

int readonly
[source]

Flag indicating if the member is read-only

const char *doc
[source]

Docstring of the member (UTF-8 encoded; may be NULL)

struct HPyGetSet
[source]

C structure to define an HPy get/set descriptor.

It is perfectly fine to fill this structure manually. However, the recommended and easier way is to use macros HPyDef_GET (to create a get descriptor only), HPyDef_SET (to create a set descriptor only), or HPyDef_GETSET (to create both).

const char *name
[source]

The name of Python attribute (UTF-8 encoded)

HPyCFunction getter_impl
[source]

Function pointer of the C getter function (may be NULL)

HPyCFunction setter_impl
[source]

Function pointer of the C setter function (may be NULL)

int getter_cpy_trampoline
[source]

Function pointer to the CPython trampoline function for the getter (may be NULL if (and only if) getter_impl == NULL)

int setter_cpy_trampoline
[source]

Function pointer to the CPython trampoline function for the setter (may be NULL if (and only if) setter_impl == NULL)

const char *doc
[source]

Docstring of the get/set descriptor (UTF-8 encoded; may be NULL)

void *closure
[source]

A value that will be passed to the getter_impl/setter_impl functions.

HPyDef_SLOT(SYM, SLOT)
[source]

A convenience macro and recommended way to create a definition for an HPy slot.

The macro generates a C global variable and an appropriate CPython trampoline function. It will fill an HPyDef structure appropriately and store it in the global variable.

This macro expects a C function SYM_impl that will be used as the implementing slot function.

Parameters
  • SYM – A C symbol name of the resulting global variable that will contain the generated HPy definition. The variable is defined as static.

  • SLOT – The HPy slot identifier.

HPyDef_METH(SYM, NAME, SIG)
[source]

A convenience macro and recommended way to create a definition for an HPy method.

The macro generates a C global variable and an appropriate CPython trampoline function. It will fill an HPyDef structure appropriately and store it in the global variable.

This macro expects a C function SYM_impl that will be used as the implementing C function.

Parameters
  • SYM – A C symbol name of the resulting global variable that will contain the generated HPy definition. The variable is defined as static.

  • NAME – The Python attribute name (UTF-8 encoded).

  • SIG – The implementation’s C signature (see HPyFunc_Signature).

HPyDef_MEMBER(SYM, NAME, TYPE, OFFSET)
[source]

A convenience macro and recommended way to create a definition for an HPy member.

The macro generates a C global variable. It will fill an HPyDef structure appropriately and store it in the global variable.

Parameters
  • SYM – A C symbol name of the resulting global variable that will contain the generated HPy definition. The variable is defined as static.

  • NAME – The Python attribute name (UTF-8 encoded).

  • TYPE – The implementation’s C signature (see HPyFunc_Signature).

  • OFFSET – The Python attribute name (UTF-8 encoded).

  • .readonly – Optional flag indicating if the member is read-only.

  • .doc – Optional docstring (UTF-8 encoded).

HPyDef_GET(SYM, NAME)
[source]

A convenience macro and recommended way to create a definition for an HPy get descriptor.

The macro generates a C global variable. It will fill an HPyDef structure appropriately and store it in the global variable.

Parameters
  • SYM – A C symbol name of the resulting global variable that will contain the generated HPy definition. The variable is defined as static.

  • NAME – The Python attribute name (UTF-8 encoded).

  • .doc – Optional docstring (UTF-8 encoded).

  • .closure – Optional pointer, providing additional data for the getter.

HPyDef_SET(SYM, NAME)
[source]

A convenience macro and recommended way to create a definition for an HPy set descriptor.

The macro generates a C global variable. It will fill an HPyDef structure appropriately and store it in the global variable.

Parameters
  • SYM – A C symbol name of the resulting global variable that will contain the generated HPy definition. The variable is defined as static.

  • NAME – The Python attribute name (UTF-8 encoded).

  • .doc – Optional docstring (UTF-8 encoded).

  • .closure – Optional pointer, providing additional data for the setter.

HPyDef_GETSET(SYM, NAME)
[source]

A convenience macro and recommended way to create a definition for an HPy get/set descriptor.

The macro generates a C global variable. It will fill an HPyDef structure appropriately and store it in the global variable.

Parameters
  • SYM – A C symbol name of the resulting global variable that will contain the generated HPy definition. The variable is defined as static.

  • NAME – The Python attribute name (UTF-8 encoded).

  • .doc – Optional docstring (UTF-8 encoded).

  • .closure – Optional pointer, providing additional data for the getter and setter.

HPyDef_CALL_FUNCTION(SYM)
[source]

A convenience macro and the recommended way to create a call function definition.

The macro generates a C global variable with name SYM. It will fill an HPyCallFunction structure appropriately and store it in the global variable.

This macro expects a C function SYM_impl that will be used as the implementing C function.

Parameters
  • SYM – A C symbol name of the resulting global variable that will contain the generated call function definition. The variable is defined as static.