mirror of https://github.com/python/cpython
218 lines
8.9 KiB
C
218 lines
8.9 KiB
C
#define PY_SSIZE_T_CLEAN
|
|
#include "parts.h"
|
|
#include <stddef.h> // for offsetof()
|
|
|
|
|
|
// This defines two classes that contain all the simple member types, one
|
|
// using "new" Py_-prefixed API, and the other using "old" <structmember.h>.
|
|
// They should behave identically in Python.
|
|
|
|
typedef struct {
|
|
char bool_member;
|
|
char byte_member;
|
|
unsigned char ubyte_member;
|
|
short short_member;
|
|
unsigned short ushort_member;
|
|
int int_member;
|
|
unsigned int uint_member;
|
|
long long_member;
|
|
unsigned long ulong_member;
|
|
Py_ssize_t pyssizet_member;
|
|
float float_member;
|
|
double double_member;
|
|
char inplace_member[6];
|
|
long long longlong_member;
|
|
unsigned long long ulonglong_member;
|
|
} all_structmembers;
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
all_structmembers structmembers;
|
|
} test_structmembers;
|
|
|
|
|
|
static struct PyMemberDef test_members_newapi[] = {
|
|
{"T_BOOL", Py_T_BOOL, offsetof(test_structmembers, structmembers.bool_member), 0, NULL},
|
|
{"T_BYTE", Py_T_BYTE, offsetof(test_structmembers, structmembers.byte_member), 0, NULL},
|
|
{"T_UBYTE", Py_T_UBYTE, offsetof(test_structmembers, structmembers.ubyte_member), 0, NULL},
|
|
{"T_SHORT", Py_T_SHORT, offsetof(test_structmembers, structmembers.short_member), 0, NULL},
|
|
{"T_USHORT", Py_T_USHORT, offsetof(test_structmembers, structmembers.ushort_member), 0, NULL},
|
|
{"T_INT", Py_T_INT, offsetof(test_structmembers, structmembers.int_member), 0, NULL},
|
|
{"T_UINT", Py_T_UINT, offsetof(test_structmembers, structmembers.uint_member), 0, NULL},
|
|
{"T_LONG", Py_T_LONG, offsetof(test_structmembers, structmembers.long_member), 0, NULL},
|
|
{"T_ULONG", Py_T_ULONG, offsetof(test_structmembers, structmembers.ulong_member), 0, NULL},
|
|
{"T_PYSSIZET", Py_T_PYSSIZET, offsetof(test_structmembers, structmembers.pyssizet_member), 0, NULL},
|
|
{"T_FLOAT", Py_T_FLOAT, offsetof(test_structmembers, structmembers.float_member), 0, NULL},
|
|
{"T_DOUBLE", Py_T_DOUBLE, offsetof(test_structmembers, structmembers.double_member), 0, NULL},
|
|
{"T_STRING_INPLACE", Py_T_STRING_INPLACE, offsetof(test_structmembers, structmembers.inplace_member), 0, NULL},
|
|
{"T_LONGLONG", Py_T_LONGLONG, offsetof(test_structmembers, structmembers.longlong_member), 0, NULL},
|
|
{"T_ULONGLONG", Py_T_ULONGLONG, offsetof(test_structmembers, structmembers.ulonglong_member), 0, NULL},
|
|
{NULL}
|
|
};
|
|
|
|
static PyObject *
|
|
test_structmembers_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|
{
|
|
static char *keywords[] = {
|
|
"T_BOOL", "T_BYTE", "T_UBYTE", "T_SHORT", "T_USHORT",
|
|
"T_INT", "T_UINT", "T_LONG", "T_ULONG", "T_PYSSIZET",
|
|
"T_FLOAT", "T_DOUBLE", "T_STRING_INPLACE",
|
|
"T_LONGLONG", "T_ULONGLONG",
|
|
NULL};
|
|
static const char fmt[] = "|bbBhHiIlknfds#LK";
|
|
test_structmembers *ob;
|
|
const char *s = NULL;
|
|
Py_ssize_t string_len = 0;
|
|
ob = PyObject_New(test_structmembers, type);
|
|
if (ob == NULL) {
|
|
return NULL;
|
|
}
|
|
memset(&ob->structmembers, 0, sizeof(all_structmembers));
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, fmt, keywords,
|
|
&ob->structmembers.bool_member,
|
|
&ob->structmembers.byte_member,
|
|
&ob->structmembers.ubyte_member,
|
|
&ob->structmembers.short_member,
|
|
&ob->structmembers.ushort_member,
|
|
&ob->structmembers.int_member,
|
|
&ob->structmembers.uint_member,
|
|
&ob->structmembers.long_member,
|
|
&ob->structmembers.ulong_member,
|
|
&ob->structmembers.pyssizet_member,
|
|
&ob->structmembers.float_member,
|
|
&ob->structmembers.double_member,
|
|
&s, &string_len,
|
|
&ob->structmembers.longlong_member,
|
|
&ob->structmembers.ulonglong_member))
|
|
{
|
|
Py_DECREF(ob);
|
|
return NULL;
|
|
}
|
|
if (s != NULL) {
|
|
if (string_len > 5) {
|
|
Py_DECREF(ob);
|
|
PyErr_SetString(PyExc_ValueError, "string too long");
|
|
return NULL;
|
|
}
|
|
strcpy(ob->structmembers.inplace_member, s);
|
|
}
|
|
else {
|
|
strcpy(ob->structmembers.inplace_member, "");
|
|
}
|
|
return (PyObject *)ob;
|
|
}
|
|
|
|
static PyType_Slot test_structmembers_slots[] = {
|
|
{Py_tp_new, test_structmembers_new},
|
|
{Py_tp_members, test_members_newapi},
|
|
{0},
|
|
};
|
|
|
|
static PyType_Spec test_structmembers_spec = {
|
|
.name = "_testcapi._test_structmembersType_NewAPI",
|
|
.flags = Py_TPFLAGS_DEFAULT,
|
|
.basicsize = sizeof(test_structmembers),
|
|
.slots = test_structmembers_slots,
|
|
};
|
|
|
|
#include <structmember.h>
|
|
|
|
static struct PyMemberDef test_members[] = {
|
|
{"T_BOOL", T_BOOL, offsetof(test_structmembers, structmembers.bool_member), 0, NULL},
|
|
{"T_BYTE", T_BYTE, offsetof(test_structmembers, structmembers.byte_member), 0, NULL},
|
|
{"T_UBYTE", T_UBYTE, offsetof(test_structmembers, structmembers.ubyte_member), 0, NULL},
|
|
{"T_SHORT", T_SHORT, offsetof(test_structmembers, structmembers.short_member), 0, NULL},
|
|
{"T_USHORT", T_USHORT, offsetof(test_structmembers, structmembers.ushort_member), 0, NULL},
|
|
{"T_INT", T_INT, offsetof(test_structmembers, structmembers.int_member), 0, NULL},
|
|
{"T_UINT", T_UINT, offsetof(test_structmembers, structmembers.uint_member), 0, NULL},
|
|
{"T_LONG", T_LONG, offsetof(test_structmembers, structmembers.long_member), 0, NULL},
|
|
{"T_ULONG", T_ULONG, offsetof(test_structmembers, structmembers.ulong_member), 0, NULL},
|
|
{"T_PYSSIZET", T_PYSSIZET, offsetof(test_structmembers, structmembers.pyssizet_member), 0, NULL},
|
|
{"T_FLOAT", T_FLOAT, offsetof(test_structmembers, structmembers.float_member), 0, NULL},
|
|
{"T_DOUBLE", T_DOUBLE, offsetof(test_structmembers, structmembers.double_member), 0, NULL},
|
|
{"T_STRING_INPLACE", T_STRING_INPLACE, offsetof(test_structmembers, structmembers.inplace_member), 0, NULL},
|
|
{"T_LONGLONG", T_LONGLONG, offsetof(test_structmembers, structmembers.longlong_member), 0, NULL},
|
|
{"T_ULONGLONG", T_ULONGLONG, offsetof(test_structmembers, structmembers.ulonglong_member), 0, NULL},
|
|
{NULL}
|
|
};
|
|
|
|
|
|
static void
|
|
test_structmembers_free(PyObject *ob)
|
|
{
|
|
PyObject_Free(ob);
|
|
}
|
|
|
|
/* Designated initializers would work too, but this does test the *old* API */
|
|
static PyTypeObject test_structmembersType_OldAPI= {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
"test_structmembersType_OldAPI",
|
|
sizeof(test_structmembers), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
test_structmembers_free, /* destructor tp_dealloc */
|
|
0, /* tp_vectorcall_offset */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_as_async */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
PyObject_GenericGetAttr, /* tp_getattro */
|
|
PyObject_GenericSetAttr, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
0, /* tp_flags */
|
|
"Type containing all structmember types",
|
|
0, /* traverseproc tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
0, /* tp_methods */
|
|
test_members, /* tp_members */
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
test_structmembers_new, /* tp_new */
|
|
};
|
|
|
|
|
|
int
|
|
_PyTestCapi_Init_Structmember(PyObject *m)
|
|
{
|
|
int res;
|
|
res = PyType_Ready(&test_structmembersType_OldAPI);
|
|
if (res < 0) {
|
|
return -1;
|
|
}
|
|
res = PyModule_AddObject(
|
|
m,
|
|
"_test_structmembersType_OldAPI",
|
|
(PyObject *)&test_structmembersType_OldAPI);
|
|
if (res < 0) {
|
|
return -1;
|
|
}
|
|
|
|
PyObject *test_structmembersType_NewAPI = PyType_FromModuleAndSpec(
|
|
m, &test_structmembers_spec, NULL);
|
|
if (!test_structmembersType_NewAPI) {
|
|
return -1;
|
|
}
|
|
res = PyModule_AddType(m, (PyTypeObject*)test_structmembersType_NewAPI);
|
|
Py_DECREF(test_structmembersType_NewAPI);
|
|
if (res < 0) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|