David Abrahams tried to compile this as a separate DLL under MSVC, and

got a barrage of compile errors that didn't make sense to the C++ brain:
MSVC does not allow C (but does allow C++) initializers to contain
data addresses supplied by other DLLs.  So changed the initializers here
to use dummy nulls, and changed module init to plug in the foreign
addresses at runtime (manually simulating what C++ does by magic).  Tested
on Windows, and Guido tested on Linux (thanks!).  BTW, the *point* is that
people are going to use this module as a template for writing their own
subtypes, and it's unusual for extension authors to build their extensions
into Python directly (separate DLLs are the norm on Windows); so it's
better if we give them a template that works <wink>.
This commit is contained in:
Tim Peters 2001-12-17 01:27:01 +00:00
parent 2168e9d602
commit dd5c05fe6d
1 changed files with 21 additions and 4 deletions

View File

@ -7,6 +7,15 @@ static char xxsubtype__doc__[] =
"If you don't care about the examples, and don't intend to run the Python\n" "If you don't care about the examples, and don't intend to run the Python\n"
"test suite, you can recompile Python without Modules/xxsubtype.c."; "test suite, you can recompile Python without Modules/xxsubtype.c.";
/* We link this module statically for convenience. If compiled as a shared
library instead, some compilers don't allow addresses of Python objects
defined in other libraries to be used in static initializers here. The
DEFERRED_ADDRESS macro is used to tag the slots where such addresses
appear; the module init function must fill in the tagged slots at runtime.
The argument is for documentation -- the macro ignores it.
*/
#define DEFERRED_ADDRESS(ADDR) 0
/* spamlist -- a list subtype */ /* spamlist -- a list subtype */
typedef struct { typedef struct {
@ -66,7 +75,7 @@ static PyGetSetDef spamlist_getsets[] = {
}; };
static PyTypeObject spamlist_type = { static PyTypeObject spamlist_type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
0, 0,
"xxsubtype.spamlist", "xxsubtype.spamlist",
sizeof(spamlistobject), sizeof(spamlistobject),
@ -97,7 +106,7 @@ static PyTypeObject spamlist_type = {
spamlist_methods, /* tp_methods */ spamlist_methods, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
spamlist_getsets, /* tp_getset */ spamlist_getsets, /* tp_getset */
&PyList_Type, /* tp_base */ DEFERRED_ADDRESS(&PyList_Type), /* tp_base */
0, /* tp_dict */ 0, /* tp_dict */
0, /* tp_descr_get */ 0, /* tp_descr_get */
0, /* tp_descr_set */ 0, /* tp_descr_set */
@ -160,7 +169,7 @@ static PyMemberDef spamdict_members[] = {
}; };
static PyTypeObject spamdict_type = { static PyTypeObject spamdict_type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
0, 0,
"xxsubtype.spamdict", "xxsubtype.spamdict",
sizeof(spamdictobject), sizeof(spamdictobject),
@ -191,7 +200,7 @@ static PyTypeObject spamdict_type = {
spamdict_methods, /* tp_methods */ spamdict_methods, /* tp_methods */
spamdict_members, /* tp_members */ spamdict_members, /* tp_members */
0, /* tp_getset */ 0, /* tp_getset */
&PyDict_Type, /* tp_base */ DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */
0, /* tp_dict */ 0, /* tp_dict */
0, /* tp_descr_get */ 0, /* tp_descr_get */
0, /* tp_descr_set */ 0, /* tp_descr_set */
@ -231,6 +240,14 @@ initxxsubtype(void)
{ {
PyObject *m, *d; PyObject *m, *d;
/* Fill in the deferred data addresses. This must be done before
PyType_Ready() is called. */
spamdict_type.ob_type = &PyType_Type;
spamdict_type.tp_base = &PyDict_Type;
spamlist_type.ob_type = &PyType_Type;
spamlist_type.tp_base = &PyList_Type;
m = Py_InitModule3("xxsubtype", m = Py_InitModule3("xxsubtype",
xxsubtype_functions, xxsubtype_functions,
xxsubtype__doc__); xxsubtype__doc__);