(root)/
Python-3.12.0/
Modules/
_testcapi/
structmember.c
       1  #define PY_SSIZE_T_CLEAN
       2  #include "parts.h"
       3  #include <stddef.h>   // for offsetof()
       4  
       5  
       6  // This defines two classes that contain all the simple member types, one
       7  // using "new" Py_-prefixed API, and the other using "old" <structmember.h>.
       8  // They should behave identically in Python.
       9  
      10  typedef struct {
      11      char bool_member;
      12      char byte_member;
      13      unsigned char ubyte_member;
      14      short short_member;
      15      unsigned short ushort_member;
      16      int int_member;
      17      unsigned int uint_member;
      18      long long_member;
      19      unsigned long ulong_member;
      20      Py_ssize_t pyssizet_member;
      21      float float_member;
      22      double double_member;
      23      char inplace_member[6];
      24      long long longlong_member;
      25      unsigned long long ulonglong_member;
      26  } all_structmembers;
      27  
      28  typedef struct {
      29      PyObject_HEAD
      30      all_structmembers structmembers;
      31  } test_structmembers;
      32  
      33  
      34  static struct PyMemberDef test_members_newapi[] = {
      35      {"T_BOOL", Py_T_BOOL, offsetof(test_structmembers, structmembers.bool_member), 0, NULL},
      36      {"T_BYTE", Py_T_BYTE, offsetof(test_structmembers, structmembers.byte_member), 0, NULL},
      37      {"T_UBYTE", Py_T_UBYTE, offsetof(test_structmembers, structmembers.ubyte_member), 0, NULL},
      38      {"T_SHORT", Py_T_SHORT, offsetof(test_structmembers, structmembers.short_member), 0, NULL},
      39      {"T_USHORT", Py_T_USHORT, offsetof(test_structmembers, structmembers.ushort_member), 0, NULL},
      40      {"T_INT", Py_T_INT, offsetof(test_structmembers, structmembers.int_member), 0, NULL},
      41      {"T_UINT", Py_T_UINT, offsetof(test_structmembers, structmembers.uint_member), 0, NULL},
      42      {"T_LONG", Py_T_LONG, offsetof(test_structmembers, structmembers.long_member), 0, NULL},
      43      {"T_ULONG", Py_T_ULONG, offsetof(test_structmembers, structmembers.ulong_member), 0, NULL},
      44      {"T_PYSSIZET", Py_T_PYSSIZET, offsetof(test_structmembers, structmembers.pyssizet_member), 0, NULL},
      45      {"T_FLOAT", Py_T_FLOAT, offsetof(test_structmembers, structmembers.float_member), 0, NULL},
      46      {"T_DOUBLE", Py_T_DOUBLE, offsetof(test_structmembers, structmembers.double_member), 0, NULL},
      47      {"T_STRING_INPLACE", Py_T_STRING_INPLACE, offsetof(test_structmembers, structmembers.inplace_member), 0, NULL},
      48      {"T_LONGLONG", Py_T_LONGLONG, offsetof(test_structmembers, structmembers.longlong_member), 0, NULL},
      49      {"T_ULONGLONG", Py_T_ULONGLONG, offsetof(test_structmembers, structmembers.ulonglong_member), 0, NULL},
      50      {NULL}
      51  };
      52  
      53  static PyObject *
      54  test_structmembers_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
      55  {
      56      static char *keywords[] = {
      57          "T_BOOL", "T_BYTE", "T_UBYTE", "T_SHORT", "T_USHORT",
      58          "T_INT", "T_UINT", "T_LONG", "T_ULONG", "T_PYSSIZET",
      59          "T_FLOAT", "T_DOUBLE", "T_STRING_INPLACE",
      60          "T_LONGLONG", "T_ULONGLONG",
      61          NULL};
      62      static const char fmt[] = "|bbBhHiIlknfds#LK";
      63      test_structmembers *ob;
      64      const char *s = NULL;
      65      Py_ssize_t string_len = 0;
      66      ob = PyObject_New(test_structmembers, type);
      67      if (ob == NULL) {
      68          return NULL;
      69      }
      70      memset(&ob->structmembers, 0, sizeof(all_structmembers));
      71      if (!PyArg_ParseTupleAndKeywords(args, kwargs, fmt, keywords,
      72                                       &ob->structmembers.bool_member,
      73                                       &ob->structmembers.byte_member,
      74                                       &ob->structmembers.ubyte_member,
      75                                       &ob->structmembers.short_member,
      76                                       &ob->structmembers.ushort_member,
      77                                       &ob->structmembers.int_member,
      78                                       &ob->structmembers.uint_member,
      79                                       &ob->structmembers.long_member,
      80                                       &ob->structmembers.ulong_member,
      81                                       &ob->structmembers.pyssizet_member,
      82                                       &ob->structmembers.float_member,
      83                                       &ob->structmembers.double_member,
      84                                       &s, &string_len,
      85                                       &ob->structmembers.longlong_member,
      86                                       &ob->structmembers.ulonglong_member))
      87      {
      88          Py_DECREF(ob);
      89          return NULL;
      90      }
      91      if (s != NULL) {
      92          if (string_len > 5) {
      93              Py_DECREF(ob);
      94              PyErr_SetString(PyExc_ValueError, "string too long");
      95              return NULL;
      96          }
      97          strcpy(ob->structmembers.inplace_member, s);
      98      }
      99      else {
     100          strcpy(ob->structmembers.inplace_member, "");
     101      }
     102      return (PyObject *)ob;
     103  }
     104  
     105  static PyType_Slot test_structmembers_slots[] = {
     106      {Py_tp_new, test_structmembers_new},
     107      {Py_tp_members, test_members_newapi},
     108      {0},
     109  };
     110  
     111  static PyType_Spec test_structmembers_spec = {
     112      .name = "_testcapi._test_structmembersType_NewAPI",
     113      .flags = Py_TPFLAGS_DEFAULT,
     114      .basicsize = sizeof(test_structmembers),
     115      .slots = test_structmembers_slots,
     116  };
     117  
     118  #include <structmember.h>
     119  
     120  static struct PyMemberDef test_members[] = {
     121      {"T_BOOL", T_BOOL, offsetof(test_structmembers, structmembers.bool_member), 0, NULL},
     122      {"T_BYTE", T_BYTE, offsetof(test_structmembers, structmembers.byte_member), 0, NULL},
     123      {"T_UBYTE", T_UBYTE, offsetof(test_structmembers, structmembers.ubyte_member), 0, NULL},
     124      {"T_SHORT", T_SHORT, offsetof(test_structmembers, structmembers.short_member), 0, NULL},
     125      {"T_USHORT", T_USHORT, offsetof(test_structmembers, structmembers.ushort_member), 0, NULL},
     126      {"T_INT", T_INT, offsetof(test_structmembers, structmembers.int_member), 0, NULL},
     127      {"T_UINT", T_UINT, offsetof(test_structmembers, structmembers.uint_member), 0, NULL},
     128      {"T_LONG", T_LONG, offsetof(test_structmembers, structmembers.long_member), 0, NULL},
     129      {"T_ULONG", T_ULONG, offsetof(test_structmembers, structmembers.ulong_member), 0, NULL},
     130      {"T_PYSSIZET", T_PYSSIZET, offsetof(test_structmembers, structmembers.pyssizet_member), 0, NULL},
     131      {"T_FLOAT", T_FLOAT, offsetof(test_structmembers, structmembers.float_member), 0, NULL},
     132      {"T_DOUBLE", T_DOUBLE, offsetof(test_structmembers, structmembers.double_member), 0, NULL},
     133      {"T_STRING_INPLACE", T_STRING_INPLACE, offsetof(test_structmembers, structmembers.inplace_member), 0, NULL},
     134      {"T_LONGLONG", T_LONGLONG, offsetof(test_structmembers, structmembers.longlong_member), 0, NULL},
     135      {"T_ULONGLONG", T_ULONGLONG, offsetof(test_structmembers, structmembers.ulonglong_member), 0, NULL},
     136      {NULL}
     137  };
     138  
     139  
     140  static void
     141  test_structmembers_free(PyObject *ob)
     142  {
     143      PyObject_Free(ob);
     144  }
     145  
     146  /* Designated initializers would work too, but this does test the *old* API */
     147  static PyTypeObject test_structmembersType_OldAPI= {
     148      PyVarObject_HEAD_INIT(NULL, 0)
     149      "test_structmembersType_OldAPI",
     150      sizeof(test_structmembers),         /* tp_basicsize */
     151      0,                                  /* tp_itemsize */
     152      test_structmembers_free,            /* destructor tp_dealloc */
     153      0,                                  /* tp_vectorcall_offset */
     154      0,                                  /* tp_getattr */
     155      0,                                  /* tp_setattr */
     156      0,                                  /* tp_as_async */
     157      0,                                  /* tp_repr */
     158      0,                                  /* tp_as_number */
     159      0,                                  /* tp_as_sequence */
     160      0,                                  /* tp_as_mapping */
     161      0,                                  /* tp_hash */
     162      0,                                  /* tp_call */
     163      0,                                  /* tp_str */
     164      PyObject_GenericGetAttr,            /* tp_getattro */
     165      PyObject_GenericSetAttr,            /* tp_setattro */
     166      0,                                  /* tp_as_buffer */
     167      0,                                  /* tp_flags */
     168      "Type containing all structmember types",
     169      0,                                  /* traverseproc tp_traverse */
     170      0,                                  /* tp_clear */
     171      0,                                  /* tp_richcompare */
     172      0,                                  /* tp_weaklistoffset */
     173      0,                                  /* tp_iter */
     174      0,                                  /* tp_iternext */
     175      0,                                  /* tp_methods */
     176      test_members,                       /* tp_members */
     177      0,
     178      0,
     179      0,
     180      0,
     181      0,
     182      0,
     183      0,
     184      0,
     185      test_structmembers_new,             /* tp_new */
     186  };
     187  
     188  
     189  int
     190  _PyTestCapi_Init_Structmember(PyObject *m)
     191  {
     192      int res;
     193      res = PyType_Ready(&test_structmembersType_OldAPI);
     194      if (res < 0) {
     195          return -1;
     196      }
     197      res = PyModule_AddObjectRef(
     198          m,
     199          "_test_structmembersType_OldAPI",
     200          (PyObject *)&test_structmembersType_OldAPI);
     201      if (res < 0) {
     202          return -1;
     203      }
     204  
     205      PyObject *test_structmembersType_NewAPI = PyType_FromModuleAndSpec(
     206          m, &test_structmembers_spec, NULL);
     207      if (!test_structmembersType_NewAPI) {
     208          return -1;
     209      }
     210      res = PyModule_AddType(m, (PyTypeObject*)test_structmembersType_NewAPI);
     211      Py_DECREF(test_structmembersType_NewAPI);
     212      if (res < 0) {
     213          return -1;
     214      }
     215  
     216      return 0;
     217  }