123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808 |
- /* Python interface to objfiles.
- Copyright (C) 2008-2022 Free Software Foundation, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "defs.h"
- #include "python-internal.h"
- #include "charset.h"
- #include "objfiles.h"
- #include "language.h"
- #include "build-id.h"
- #include "symtab.h"
- struct objfile_object
- {
- PyObject_HEAD
- /* The corresponding objfile. */
- struct objfile *objfile;
- /* Dictionary holding user-added attributes.
- This is the __dict__ attribute of the object. */
- PyObject *dict;
- /* The pretty-printer list of functions. */
- PyObject *printers;
- /* The frame filter list of functions. */
- PyObject *frame_filters;
- /* The list of frame unwinders. */
- PyObject *frame_unwinders;
- /* The type-printer list. */
- PyObject *type_printers;
- /* The debug method matcher list. */
- PyObject *xmethods;
- };
- extern PyTypeObject objfile_object_type
- CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("objfile_object");
- static const struct objfile_data *objfpy_objfile_data_key;
- /* Require that OBJF be a valid objfile. */
- #define OBJFPY_REQUIRE_VALID(obj) \
- do { \
- if (!(obj)->objfile) \
- { \
- PyErr_SetString (PyExc_RuntimeError, \
- _("Objfile no longer exists.")); \
- return NULL; \
- } \
- } while (0)
- /* An Objfile method which returns the objfile's file name, or None. */
- static PyObject *
- objfpy_get_filename (PyObject *self, void *closure)
- {
- objfile_object *obj = (objfile_object *) self;
- if (obj->objfile)
- return (host_string_to_python_string (objfile_name (obj->objfile))
- .release ());
- Py_RETURN_NONE;
- }
- /* An Objfile method which returns the objfile's file name, as specified
- by the user, or None. */
- static PyObject *
- objfpy_get_username (PyObject *self, void *closure)
- {
- objfile_object *obj = (objfile_object *) self;
- if (obj->objfile)
- {
- const char *username = obj->objfile->original_name;
- return host_string_to_python_string (username).release ();
- }
- Py_RETURN_NONE;
- }
- /* If SELF is a separate debug-info file, return the "backlink" field.
- Otherwise return None. */
- static PyObject *
- objfpy_get_owner (PyObject *self, void *closure)
- {
- objfile_object *obj = (objfile_object *) self;
- struct objfile *objfile = obj->objfile;
- struct objfile *owner;
- OBJFPY_REQUIRE_VALID (obj);
- owner = objfile->separate_debug_objfile_backlink;
- if (owner != NULL)
- return objfile_to_objfile_object (owner).release ();
- Py_RETURN_NONE;
- }
- /* An Objfile method which returns the objfile's build id, or None. */
- static PyObject *
- objfpy_get_build_id (PyObject *self, void *closure)
- {
- objfile_object *obj = (objfile_object *) self;
- struct objfile *objfile = obj->objfile;
- const struct bfd_build_id *build_id = NULL;
- OBJFPY_REQUIRE_VALID (obj);
- try
- {
- build_id = build_id_bfd_get (objfile->obfd);
- }
- catch (const gdb_exception &except)
- {
- GDB_PY_HANDLE_EXCEPTION (except);
- }
- if (build_id != NULL)
- {
- std::string hex_form = bin2hex (build_id->data, build_id->size);
- return host_string_to_python_string (hex_form.c_str ()).release ();
- }
- Py_RETURN_NONE;
- }
- /* An Objfile method which returns the objfile's progspace, or None. */
- static PyObject *
- objfpy_get_progspace (PyObject *self, void *closure)
- {
- objfile_object *obj = (objfile_object *) self;
- if (obj->objfile)
- return pspace_to_pspace_object (obj->objfile->pspace).release ();
- Py_RETURN_NONE;
- }
- static void
- objfpy_dealloc (PyObject *o)
- {
- objfile_object *self = (objfile_object *) o;
- Py_XDECREF (self->dict);
- Py_XDECREF (self->printers);
- Py_XDECREF (self->frame_filters);
- Py_XDECREF (self->frame_unwinders);
- Py_XDECREF (self->type_printers);
- Py_XDECREF (self->xmethods);
- Py_TYPE (self)->tp_free (self);
- }
- /* Initialize an objfile_object.
- The result is a boolean indicating success. */
- static int
- objfpy_initialize (objfile_object *self)
- {
- self->objfile = NULL;
- self->dict = PyDict_New ();
- if (self->dict == NULL)
- return 0;
- self->printers = PyList_New (0);
- if (self->printers == NULL)
- return 0;
- self->frame_filters = PyDict_New ();
- if (self->frame_filters == NULL)
- return 0;
- self->frame_unwinders = PyList_New (0);
- if (self->frame_unwinders == NULL)
- return 0;
- self->type_printers = PyList_New (0);
- if (self->type_printers == NULL)
- return 0;
- self->xmethods = PyList_New (0);
- if (self->xmethods == NULL)
- return 0;
- return 1;
- }
- static PyObject *
- objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
- {
- gdbpy_ref<objfile_object> self ((objfile_object *) type->tp_alloc (type, 0));
- if (self != NULL)
- {
- if (!objfpy_initialize (self.get ()))
- return NULL;
- }
- return (PyObject *) self.release ();
- }
- PyObject *
- objfpy_get_printers (PyObject *o, void *ignore)
- {
- objfile_object *self = (objfile_object *) o;
- Py_INCREF (self->printers);
- return self->printers;
- }
- static int
- objfpy_set_printers (PyObject *o, PyObject *value, void *ignore)
- {
- objfile_object *self = (objfile_object *) o;
- if (! value)
- {
- PyErr_SetString (PyExc_TypeError,
- _("Cannot delete the pretty_printers attribute."));
- return -1;
- }
- if (! PyList_Check (value))
- {
- PyErr_SetString (PyExc_TypeError,
- _("The pretty_printers attribute must be a list."));
- return -1;
- }
- /* Take care in case the LHS and RHS are related somehow. */
- gdbpy_ref<> tmp (self->printers);
- Py_INCREF (value);
- self->printers = value;
- return 0;
- }
- /* Return the Python dictionary attribute containing frame filters for
- this object file. */
- PyObject *
- objfpy_get_frame_filters (PyObject *o, void *ignore)
- {
- objfile_object *self = (objfile_object *) o;
- Py_INCREF (self->frame_filters);
- return self->frame_filters;
- }
- /* Set this object file's frame filters dictionary to FILTERS. */
- static int
- objfpy_set_frame_filters (PyObject *o, PyObject *filters, void *ignore)
- {
- objfile_object *self = (objfile_object *) o;
- if (! filters)
- {
- PyErr_SetString (PyExc_TypeError,
- _("Cannot delete the frame filters attribute."));
- return -1;
- }
- if (! PyDict_Check (filters))
- {
- PyErr_SetString (PyExc_TypeError,
- _("The frame_filters attribute must be a dictionary."));
- return -1;
- }
- /* Take care in case the LHS and RHS are related somehow. */
- gdbpy_ref<> tmp (self->frame_filters);
- Py_INCREF (filters);
- self->frame_filters = filters;
- return 0;
- }
- /* Return the frame unwinders attribute for this object file. */
- PyObject *
- objfpy_get_frame_unwinders (PyObject *o, void *ignore)
- {
- objfile_object *self = (objfile_object *) o;
- Py_INCREF (self->frame_unwinders);
- return self->frame_unwinders;
- }
- /* Set this object file's frame unwinders list to UNWINDERS. */
- static int
- objfpy_set_frame_unwinders (PyObject *o, PyObject *unwinders, void *ignore)
- {
- objfile_object *self = (objfile_object *) o;
- if (!unwinders)
- {
- PyErr_SetString (PyExc_TypeError,
- _("Cannot delete the frame unwinders attribute."));
- return -1;
- }
- if (!PyList_Check (unwinders))
- {
- PyErr_SetString (PyExc_TypeError,
- _("The frame_unwinders attribute must be a list."));
- return -1;
- }
- /* Take care in case the LHS and RHS are related somehow. */
- gdbpy_ref<> tmp (self->frame_unwinders);
- Py_INCREF (unwinders);
- self->frame_unwinders = unwinders;
- return 0;
- }
- /* Get the 'type_printers' attribute. */
- static PyObject *
- objfpy_get_type_printers (PyObject *o, void *ignore)
- {
- objfile_object *self = (objfile_object *) o;
- Py_INCREF (self->type_printers);
- return self->type_printers;
- }
- /* Get the 'xmethods' attribute. */
- PyObject *
- objfpy_get_xmethods (PyObject *o, void *ignore)
- {
- objfile_object *self = (objfile_object *) o;
- Py_INCREF (self->xmethods);
- return self->xmethods;
- }
- /* Set the 'type_printers' attribute. */
- static int
- objfpy_set_type_printers (PyObject *o, PyObject *value, void *ignore)
- {
- objfile_object *self = (objfile_object *) o;
- if (! value)
- {
- PyErr_SetString (PyExc_TypeError,
- _("Cannot delete the type_printers attribute."));
- return -1;
- }
- if (! PyList_Check (value))
- {
- PyErr_SetString (PyExc_TypeError,
- _("The type_printers attribute must be a list."));
- return -1;
- }
- /* Take care in case the LHS and RHS are related somehow. */
- gdbpy_ref<> tmp (self->type_printers);
- Py_INCREF (value);
- self->type_printers = value;
- return 0;
- }
- /* Implementation of gdb.Objfile.is_valid (self) -> Boolean.
- Returns True if this object file still exists in GDB. */
- static PyObject *
- objfpy_is_valid (PyObject *self, PyObject *args)
- {
- objfile_object *obj = (objfile_object *) self;
- if (! obj->objfile)
- Py_RETURN_FALSE;
- Py_RETURN_TRUE;
- }
- /* Implementation of gdb.Objfile.add_separate_debug_file (self, string). */
- static PyObject *
- objfpy_add_separate_debug_file (PyObject *self, PyObject *args, PyObject *kw)
- {
- static const char *keywords[] = { "file_name", NULL };
- objfile_object *obj = (objfile_object *) self;
- const char *file_name;
- OBJFPY_REQUIRE_VALID (obj);
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, &file_name))
- return NULL;
- try
- {
- gdb_bfd_ref_ptr abfd (symfile_bfd_open (file_name));
- symbol_file_add_separate (abfd.get (), file_name, 0, obj->objfile);
- }
- catch (const gdb_exception &except)
- {
- GDB_PY_HANDLE_EXCEPTION (except);
- }
- Py_RETURN_NONE;
- }
- /* Implementation of
- gdb.Objfile.lookup_global_symbol (self, string [, domain]) -> gdb.Symbol. */
- static PyObject *
- objfpy_lookup_global_symbol (PyObject *self, PyObject *args, PyObject *kw)
- {
- static const char *keywords[] = { "name", "domain", NULL };
- objfile_object *obj = (objfile_object *) self;
- const char *symbol_name;
- int domain = VAR_DOMAIN;
- OBJFPY_REQUIRE_VALID (obj);
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|i", keywords, &symbol_name,
- &domain))
- return nullptr;
- try
- {
- struct symbol *sym = lookup_global_symbol_from_objfile
- (obj->objfile, GLOBAL_BLOCK, symbol_name, (domain_enum) domain).symbol;
- if (sym == nullptr)
- Py_RETURN_NONE;
- return symbol_to_symbol_object (sym);
- }
- catch (const gdb_exception &except)
- {
- GDB_PY_HANDLE_EXCEPTION (except);
- }
- Py_RETURN_NONE;
- }
- /* Implementation of
- gdb.Objfile.lookup_static_symbol (self, string [, domain]) -> gdb.Symbol. */
- static PyObject *
- objfpy_lookup_static_symbol (PyObject *self, PyObject *args, PyObject *kw)
- {
- static const char *keywords[] = { "name", "domain", NULL };
- objfile_object *obj = (objfile_object *) self;
- const char *symbol_name;
- int domain = VAR_DOMAIN;
- OBJFPY_REQUIRE_VALID (obj);
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|i", keywords, &symbol_name,
- &domain))
- return nullptr;
- try
- {
- struct symbol *sym = lookup_global_symbol_from_objfile
- (obj->objfile, STATIC_BLOCK, symbol_name, (domain_enum) domain).symbol;
- if (sym == nullptr)
- Py_RETURN_NONE;
- return symbol_to_symbol_object (sym);
- }
- catch (const gdb_exception &except)
- {
- GDB_PY_HANDLE_EXCEPTION (except);
- }
- Py_RETURN_NONE;
- }
- /* Implement repr() for gdb.Objfile. */
- static PyObject *
- objfpy_repr (PyObject *self_)
- {
- objfile_object *self = (objfile_object *) self_;
- objfile *obj = self->objfile;
- if (obj == nullptr)
- return PyUnicode_FromString ("<gdb.Objfile (invalid)>");
- return PyUnicode_FromFormat ("<gdb.Objfile filename=%s>",
- objfile_name (obj));
- }
- /* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it.
- Return non-zero if STRING is a potentially valid build id. */
- static int
- objfpy_build_id_ok (const char *string)
- {
- size_t i, n = strlen (string);
- if (n % 2 != 0)
- return 0;
- for (i = 0; i < n; ++i)
- {
- if (!isxdigit (string[i]))
- return 0;
- }
- return 1;
- }
- /* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it.
- Returns non-zero if BUILD_ID matches STRING.
- It is assumed that objfpy_build_id_ok (string) returns TRUE. */
- static int
- objfpy_build_id_matches (const struct bfd_build_id *build_id,
- const char *string)
- {
- size_t i;
- if (strlen (string) != 2 * build_id->size)
- return 0;
- for (i = 0; i < build_id->size; ++i)
- {
- char c1 = string[i * 2], c2 = string[i * 2 + 1];
- int byte = (fromhex (c1) << 4) | fromhex (c2);
- if (byte != build_id->data[i])
- return 0;
- }
- return 1;
- }
- /* Subroutine of gdbpy_lookup_objfile to simplify it.
- Look up an objfile by its file name. */
- static struct objfile *
- objfpy_lookup_objfile_by_name (const char *name)
- {
- for (objfile *objfile : current_program_space->objfiles ())
- {
- const char *filename;
- if ((objfile->flags & OBJF_NOT_FILENAME) != 0)
- continue;
- /* Don't return separate debug files. */
- if (objfile->separate_debug_objfile_backlink != NULL)
- continue;
- filename = objfile_filename (objfile);
- if (filename != NULL && compare_filenames_for_search (filename, name))
- return objfile;
- if (compare_filenames_for_search (objfile->original_name, name))
- return objfile;
- }
- return NULL;
- }
- /* Subroutine of gdbpy_lookup_objfile to simplify it.
- Look up an objfile by its build id. */
- static struct objfile *
- objfpy_lookup_objfile_by_build_id (const char *build_id)
- {
- for (objfile *objfile : current_program_space->objfiles ())
- {
- const struct bfd_build_id *obfd_build_id;
- if (objfile->obfd == NULL)
- continue;
- /* Don't return separate debug files. */
- if (objfile->separate_debug_objfile_backlink != NULL)
- continue;
- obfd_build_id = build_id_bfd_get (objfile->obfd);
- if (obfd_build_id == NULL)
- continue;
- if (objfpy_build_id_matches (obfd_build_id, build_id))
- return objfile;
- }
- return NULL;
- }
- /* Implementation of gdb.lookup_objfile. */
- PyObject *
- gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
- {
- static const char *keywords[] = { "name", "by_build_id", NULL };
- const char *name;
- PyObject *by_build_id_obj = NULL;
- int by_build_id;
- struct objfile *objfile;
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!", keywords,
- &name, &PyBool_Type, &by_build_id_obj))
- return NULL;
- by_build_id = 0;
- if (by_build_id_obj != NULL)
- {
- int cmp = PyObject_IsTrue (by_build_id_obj);
- if (cmp < 0)
- return NULL;
- by_build_id = cmp;
- }
- if (by_build_id)
- {
- if (!objfpy_build_id_ok (name))
- {
- PyErr_SetString (PyExc_TypeError, _("Not a valid build id."));
- return NULL;
- }
- objfile = objfpy_lookup_objfile_by_build_id (name);
- }
- else
- objfile = objfpy_lookup_objfile_by_name (name);
- if (objfile != NULL)
- return objfile_to_objfile_object (objfile).release ();
- PyErr_SetString (PyExc_ValueError, _("Objfile not found."));
- return NULL;
- }
- /* Clear the OBJFILE pointer in an Objfile object and remove the
- reference. */
- static void
- py_free_objfile (struct objfile *objfile, void *datum)
- {
- gdbpy_enter enter_py (objfile->arch ());
- gdbpy_ref<objfile_object> object ((objfile_object *) datum);
- object->objfile = NULL;
- }
- /* Return a new reference to the Python object of type Objfile
- representing OBJFILE. If the object has already been created,
- return it. Otherwise, create it. Return NULL and set the Python
- error on failure. */
- gdbpy_ref<>
- objfile_to_objfile_object (struct objfile *objfile)
- {
- PyObject *result
- = ((PyObject *) objfile_data (objfile, objfpy_objfile_data_key));
- if (result == NULL)
- {
- gdbpy_ref<objfile_object> object
- ((objfile_object *) PyObject_New (objfile_object, &objfile_object_type));
- if (object == NULL)
- return NULL;
- if (!objfpy_initialize (object.get ()))
- return NULL;
- object->objfile = objfile;
- set_objfile_data (objfile, objfpy_objfile_data_key, object.get ());
- result = (PyObject *) object.release ();
- }
- return gdbpy_ref<>::new_reference (result);
- }
- void _initialize_py_objfile ();
- void
- _initialize_py_objfile ()
- {
- objfpy_objfile_data_key
- = register_objfile_data_with_cleanup (NULL, py_free_objfile);
- }
- int
- gdbpy_initialize_objfile (void)
- {
- if (PyType_Ready (&objfile_object_type) < 0)
- return -1;
- return gdb_pymodule_addobject (gdb_module, "Objfile",
- (PyObject *) &objfile_object_type);
- }
- static PyMethodDef objfile_object_methods[] =
- {
- { "is_valid", objfpy_is_valid, METH_NOARGS,
- "is_valid () -> Boolean.\n\
- Return true if this object file is valid, false if not." },
- { "add_separate_debug_file", (PyCFunction) objfpy_add_separate_debug_file,
- METH_VARARGS | METH_KEYWORDS,
- "add_separate_debug_file (file_name).\n\
- Add FILE_NAME to the list of files containing debug info for the objfile." },
- { "lookup_global_symbol", (PyCFunction) objfpy_lookup_global_symbol,
- METH_VARARGS | METH_KEYWORDS,
- "lookup_global_symbol (name [, domain]).\n\
- Look up a global symbol in this objfile and return it." },
- { "lookup_static_symbol", (PyCFunction) objfpy_lookup_static_symbol,
- METH_VARARGS | METH_KEYWORDS,
- "lookup_static_symbol (name [, domain]).\n\
- Look up a static-linkage global symbol in this objfile and return it." },
- { NULL }
- };
- static gdb_PyGetSetDef objfile_getset[] =
- {
- { "__dict__", gdb_py_generic_dict, NULL,
- "The __dict__ for this objfile.", &objfile_object_type },
- { "filename", objfpy_get_filename, NULL,
- "The objfile's filename, or None.", NULL },
- { "username", objfpy_get_username, NULL,
- "The name of the objfile as provided by the user, or None.", NULL },
- { "owner", objfpy_get_owner, NULL,
- "The objfile owner of separate debug info objfiles, or None.",
- NULL },
- { "build_id", objfpy_get_build_id, NULL,
- "The objfile's build id, or None.", NULL },
- { "progspace", objfpy_get_progspace, NULL,
- "The objfile's progspace, or None.", NULL },
- { "pretty_printers", objfpy_get_printers, objfpy_set_printers,
- "Pretty printers.", NULL },
- { "frame_filters", objfpy_get_frame_filters,
- objfpy_set_frame_filters, "Frame Filters.", NULL },
- { "frame_unwinders", objfpy_get_frame_unwinders,
- objfpy_set_frame_unwinders, "Frame Unwinders", NULL },
- { "type_printers", objfpy_get_type_printers, objfpy_set_type_printers,
- "Type printers.", NULL },
- { "xmethods", objfpy_get_xmethods, NULL,
- "Debug methods.", NULL },
- { NULL }
- };
- PyTypeObject objfile_object_type =
- {
- PyVarObject_HEAD_INIT (NULL, 0)
- "gdb.Objfile", /*tp_name*/
- sizeof (objfile_object), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- objfpy_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- objfpy_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- "GDB objfile object", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- objfile_object_methods, /* tp_methods */
- 0, /* tp_members */
- objfile_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof (objfile_object, dict), /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- objfpy_new, /* tp_new */
- };
|