static verifyfunc createBarTypeWithMembers()

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());
  };
}