in ext/Objects/typeobject-test.cpp [2272:2399]
static verifyfunc createBarTypeWithMembers() {
struct BarObject {
PyObject_HEAD
char t_bool;
char t_byte;
unsigned char t_ubyte;
short t_short;
unsigned short t_ushort;
int t_int;
unsigned int t_uint;
long t_long;
unsigned long t_ulong;
Py_ssize_t t_pyssizet;
float t_float;
double t_double;
const char* t_string;
char t_char;
PyObject* t_object;
PyObject* t_object_null;
long long t_longlong;
unsigned long long t_ulonglong;
};
static const PyMemberDef members[] = {
{"t_bool", T_BOOL, offsetof(BarObject, t_bool)},
{"t_byte", T_BYTE, offsetof(BarObject, t_byte)},
{"t_ubyte", T_UBYTE, offsetof(BarObject, t_ubyte)},
{"t_short", T_SHORT, offsetof(BarObject, t_short)},
{"t_ushort", T_USHORT, offsetof(BarObject, t_ushort)},
{"t_int", T_INT, offsetof(BarObject, t_int)},
{"t_uint", T_UINT, offsetof(BarObject, t_uint)},
{"t_long", T_LONG, offsetof(BarObject, t_long)},
{"t_ulong", T_ULONG, offsetof(BarObject, t_ulong)},
{"t_pyssize", T_PYSSIZET, offsetof(BarObject, t_pyssizet)},
{"t_float", T_FLOAT, offsetof(BarObject, t_float)},
{"t_double", T_DOUBLE, offsetof(BarObject, t_double)},
{"t_string", T_STRING, offsetof(BarObject, t_string)},
{"t_char", T_CHAR, offsetof(BarObject, t_char)},
{"t_object", T_OBJECT, offsetof(BarObject, t_object)},
{"t_object_null", T_OBJECT, offsetof(BarObject, t_object_null)},
{"t_objectex", T_OBJECT_EX, offsetof(BarObject, t_object)},
{"t_objectex_null", T_OBJECT_EX, offsetof(BarObject, t_object_null)},
{"t_longlong", T_LONGLONG, offsetof(BarObject, t_longlong)},
{"t_ulonglong", T_ULONGLONG, offsetof(BarObject, t_ulonglong)},
{"t_int_readonly", T_INT, offsetof(BarObject, t_int), READONLY},
{nullptr},
};
newfunc new_func = [](PyTypeObject* type, PyObject*, PyObject*) {
void* slot = PyType_GetSlot(type, Py_tp_alloc);
return reinterpret_cast<allocfunc>(slot)(type, 0);
};
freefunc dealloc_func = [](void* self_ptr) {
PyObject* self = static_cast<PyObject*>(self_ptr);
BarObject* self_bar = static_cast<BarObject*>(self_ptr);
// Guaranteed to be null or initialized by something
Py_XDECREF(self_bar->t_object);
PyTypeObject* type = Py_TYPE(self);
// Since this object is subtypable (has Py_TPFLAGS_BASETYPE), we must pull
// out tp_free slot instead of calling PyObject_Del.
void* slot = PyType_GetSlot(type, Py_tp_free);
assert(slot != nullptr);
reinterpret_cast<freefunc>(slot)(self);
Py_DECREF(type);
};
initproc init_func = [](PyObject* self, PyObject*, PyObject*) {
BarObject* bar_obj = reinterpret_cast<BarObject*>(self);
bar_obj->t_bool = 1;
bar_obj->t_byte = -12;
bar_obj->t_ubyte = std::numeric_limits<unsigned char>::max();
bar_obj->t_short = -12;
bar_obj->t_ushort = std::numeric_limits<unsigned short>::max();
bar_obj->t_int = -1234;
bar_obj->t_uint = std::numeric_limits<unsigned int>::max();
bar_obj->t_long = -1234;
bar_obj->t_ulong = std::numeric_limits<unsigned long>::max();
bar_obj->t_pyssizet = 1234;
bar_obj->t_float = 1.0;
bar_obj->t_double = 1.0;
bar_obj->t_string = "foo";
bar_obj->t_char = 'a';
bar_obj->t_object = PyList_New(0);
bar_obj->t_object_null = nullptr;
bar_obj->t_longlong = std::numeric_limits<long long>::max();
bar_obj->t_ulonglong = std::numeric_limits<unsigned long long>::max();
return 0;
};
static const PyType_Slot slots[] = {
{Py_tp_new, reinterpret_cast<void*>(new_func)},
{Py_tp_init, reinterpret_cast<void*>(init_func)},
{Py_tp_dealloc, reinterpret_cast<void*>(dealloc_func)},
{Py_tp_members, const_cast<PyMemberDef*>(members)},
{0, nullptr},
};
static PyType_Spec spec = {
"__main__.Bar",
sizeof(BarObject),
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
const_cast<PyType_Slot*>(slots),
};
PyObjectPtr type(PyType_FromSpec(&spec));
moduleSet("__main__", "Bar", type);
// Verifies the original values
return [](PyObject* self) {
BarObject* bar_obj = reinterpret_cast<BarObject*>(self);
ASSERT_EQ(bar_obj->t_bool, 1);
ASSERT_EQ(bar_obj->t_byte, -12);
ASSERT_EQ(bar_obj->t_ubyte, std::numeric_limits<unsigned char>::max());
ASSERT_EQ(bar_obj->t_short, -12);
ASSERT_EQ(bar_obj->t_ushort, std::numeric_limits<unsigned short>::max());
ASSERT_EQ(bar_obj->t_int, -1234);
ASSERT_EQ(bar_obj->t_uint, std::numeric_limits<unsigned int>::max());
ASSERT_EQ(bar_obj->t_long, -1234);
ASSERT_EQ(bar_obj->t_ulong, std::numeric_limits<unsigned long>::max());
ASSERT_EQ(bar_obj->t_pyssizet, 1234);
ASSERT_EQ(bar_obj->t_float, 1.0);
ASSERT_EQ(bar_obj->t_double, 1.0);
ASSERT_EQ(bar_obj->t_string, "foo");
ASSERT_EQ(bar_obj->t_char, 'a');
ASSERT_TRUE(PyList_CheckExact(bar_obj->t_object));
ASSERT_EQ(PyList_Size(bar_obj->t_object), 0);
ASSERT_EQ(bar_obj->t_object_null, nullptr);
ASSERT_EQ(bar_obj->t_longlong, std::numeric_limits<long long>::max());
ASSERT_EQ(bar_obj->t_ulonglong,
std::numeric_limits<unsigned long long>::max());
};
}