Commit ebf3ea08 authored by David Gobbi's avatar David Gobbi Committed by Ben Boeckel

Fix PyTypeObject multiplicity (module boundaries).

When the VTK Python extension modules are loaded more than once
(e.g. by multiple Python interpreters in the same process), we
must ignore any PyTypeObjects except for the ones from the first
load.  This fixes crashes that started occurring when we moved
the PyTypeObjects from the shared PythonD libraries into the
Python modules themselves.
parent 54631aac
......@@ -58,33 +58,30 @@ PyVTKClass::PyVTKClass(
//--------------------------------------------------------------------
// Add a class, add methods and members to its type object. A return
// value of nullptr signifies that the class was already added.
PyVTKClass *PyVTKClass_Add(
PyTypeObject *PyVTKClass_Add(
PyTypeObject *pytype, PyMethodDef *methods,
const char *classname, vtknewfunc constructor)
{
// Add this type to the vtk class map
PyVTKClass *info =
vtkPythonUtil::AddClassToMap(
// Check whether the type is already in the map (use classname as key),
// and return it if so. If not, then add it to the map.
pytype = vtkPythonUtil::AddClassToMap(
pytype, methods, classname, constructor);
if (info == nullptr)
{
// The class was already in the map, so do nothing
return info;
}
// Cache the type object for vtkObjectBase for quick access
if (PyVTKObject_Type == nullptr && strcmp(classname, "vtkObjectBase") == 0)
{
PyVTKObject_Type = pytype;
}
// Create the dict
if (pytype->tp_dict == nullptr)
// If type object already has a dict, we're done
if (pytype->tp_dict)
{
pytype->tp_dict = PyDict_New();
return pytype;
}
// Create the dict
pytype->tp_dict = PyDict_New();
// Add special attribute __vtkname__
PyObject *s = PyString_FromString(classname);
PyDict_SetItemString(pytype->tp_dict, "__vtkname__", s);
......@@ -98,7 +95,7 @@ PyVTKClass *PyVTKClass_Add(
Py_DECREF(func);
}
return info;
return pytype;
}
//--------------------------------------------------------------------
......
......@@ -68,7 +68,7 @@ extern VTKWRAPPINGPYTHONCORE_EXPORT PyBufferProcs PyVTKObject_AsBuffer;
extern "C"
{
VTKWRAPPINGPYTHONCORE_EXPORT
PyVTKClass *PyVTKClass_Add(
PyTypeObject *PyVTKClass_Add(
PyTypeObject *pytype, PyMethodDef *methods, const char *classname,
vtknewfunc constructor);
......
......@@ -238,26 +238,23 @@ PyObject *PyVTKSpecialObject_CopyNew(const char *classname, const void *ptr)
//--------------------------------------------------------------------
// Add a special type, add methods and members to its type object.
// A return value of nullptr signifies that it was already added.
PyVTKSpecialType *PyVTKSpecialType_Add(PyTypeObject *pytype,
PyTypeObject *PyVTKSpecialType_Add(PyTypeObject *pytype,
PyMethodDef *methods, PyMethodDef *constructors,
vtkcopyfunc copyfunc)
{
// Add this type to the special type map
PyVTKSpecialType *info =
vtkPythonUtil::AddSpecialTypeToMap(
// Check whether the type is already in the map (use classname as key),
// and return it if so. If not, then add it to the map.
pytype = vtkPythonUtil::AddSpecialTypeToMap(
pytype, methods, constructors, copyfunc);
if (info == nullptr)
// If type object already has a dict, we're done
if (pytype->tp_dict)
{
// The type was already in the map, so do nothing
return info;
return pytype;
}
// Create the dict
if (pytype->tp_dict == nullptr)
{
pytype->tp_dict = PyDict_New();
}
pytype->tp_dict = PyDict_New();
// Add all of the methods
for (PyMethodDef *meth = methods; meth && meth->ml_name; meth++)
......@@ -267,5 +264,5 @@ PyVTKSpecialType *PyVTKSpecialType_Add(PyTypeObject *pytype,
Py_DECREF(func);
}
return info;
return pytype;
}
......@@ -64,7 +64,7 @@ struct PyVTKSpecialObject {
extern "C"
{
VTKWRAPPINGPYTHONCORE_EXPORT
PyVTKSpecialType *PyVTKSpecialType_Add(PyTypeObject *pytype,
PyTypeObject *PyVTKSpecialType_Add(PyTypeObject *pytype,
PyMethodDef *methods, PyMethodDef *constructors, vtkcopyfunc copyfunc);
VTKWRAPPINGPYTHONCORE_EXPORT
......
......@@ -254,35 +254,25 @@ void vtkPythonUtil::UnRegisterPythonCommand(vtkPythonCommand* cmd)
}
//--------------------------------------------------------------------
PyVTKSpecialType *vtkPythonUtil::AddSpecialTypeToMap(
PyTypeObject *vtkPythonUtil::AddSpecialTypeToMap(
PyTypeObject *pytype, PyMethodDef *methods, PyMethodDef *constructors,
vtkcopyfunc copyfunc)
{
const char *classname = vtkPythonUtil::StripModule(pytype->tp_name);
vtkPythonUtilCreateIfNeeded();
#ifdef VTKPYTHONDEBUG
// vtkGenericWarningMacro("Adding an type " << type << " to map ptr");
#endif
// lets make sure it isn't already there
vtkPythonSpecialTypeMap::iterator i =
vtkPythonMap->SpecialTypeMap->find(classname);
if (i != vtkPythonMap->SpecialTypeMap->end())
if (i == vtkPythonMap->SpecialTypeMap->end())
{
return nullptr;
i = vtkPythonMap->SpecialTypeMap->insert(i,
vtkPythonSpecialTypeMap::value_type(
classname,
PyVTKSpecialType(pytype, methods, constructors, copyfunc)));
}
i = vtkPythonMap->SpecialTypeMap->insert(i,
vtkPythonSpecialTypeMap::value_type(
classname,
PyVTKSpecialType(pytype, methods, constructors, copyfunc)));
#ifdef VTKPYTHONDEBUG
// vtkGenericWarningMacro("Added type to map type = " << typeObject);
#endif
return &i->second;
return i->second.py_type;
}
//--------------------------------------------------------------------
......@@ -477,10 +467,10 @@ const char *vtkPythonUtil::PythonicClassName(const char *classname)
if (*cp != '\0')
{
/* look up class and get its pythonic name */
PyVTKClass *o = vtkPythonUtil::FindClass(classname);
if (o)
PyTypeObject *pytype = vtkPythonUtil::FindClassTypeObject(classname);
if (pytype)
{
classname = vtkPythonUtil::StripModule(o->py_type->tp_name);
classname = vtkPythonUtil::StripModule(pytype->tp_name);
}
}
......@@ -503,7 +493,7 @@ const char *vtkPythonUtil::StripModule(const char *tpname)
}
//--------------------------------------------------------------------
PyVTKClass *vtkPythonUtil::AddClassToMap(
PyTypeObject *vtkPythonUtil::AddClassToMap(
PyTypeObject *pytype, PyMethodDef *methods,
const char *classname, vtknewfunc constructor)
{
......@@ -512,17 +502,15 @@ PyVTKClass *vtkPythonUtil::AddClassToMap(
// lets make sure it isn't already there
vtkPythonClassMap::iterator i =
vtkPythonMap->ClassMap->find(classname);
if (i != vtkPythonMap->ClassMap->end())
if (i == vtkPythonMap->ClassMap->end())
{
return nullptr;
i = vtkPythonMap->ClassMap->insert(i,
vtkPythonClassMap::value_type(
classname,
PyVTKClass(pytype, methods, classname, constructor)));
}
i = vtkPythonMap->ClassMap->insert(i,
vtkPythonClassMap::value_type(
classname,
PyVTKClass(pytype, methods, classname, constructor)));
return &i->second;
return i->second.py_type;
}
//--------------------------------------------------------------------
......
......@@ -66,7 +66,7 @@ public:
* Add a PyVTKClass to the type lookup table, this allows us to later
* create object given only the class name.
*/
static PyVTKClass *AddClassToMap(
static PyTypeObject *AddClassToMap(
PyTypeObject *pytype, PyMethodDef *methods,
const char *classname, vtknewfunc constructor);
......@@ -134,7 +134,7 @@ public:
* Add a special VTK type to the type lookup table, this allows us to
* later create object given only the class name.
*/
static PyVTKSpecialType *AddSpecialTypeToMap(
static PyTypeObject *AddSpecialTypeToMap(
PyTypeObject *pytype, PyMethodDef *methods, PyMethodDef *constructors,
vtkcopyfunc copyfunc);
......
......@@ -421,7 +421,7 @@ static void vtkWrapPython_GenerateObjectNew(
fprintf(fp,
"PyObject *Py%s_ClassNew()\n"
"{\n"
" PyVTKClass_Add(\n"
" PyTypeObject *pytype = PyVTKClass_Add(\n"
" &Py%s_Type, Py%s_Methods,\n",
classname, classname, classname);
......@@ -451,10 +451,6 @@ static void vtkWrapPython_GenerateObjectNew(
" nullptr);\n\n");
}
fprintf(fp,
" PyTypeObject *pytype = &Py%s_Type;\n\n",
classname);
/* if type is already ready, then return */
fprintf(fp,
" if ((pytype->tp_flags & Py_TPFLAGS_READY) != 0)\n"
......
......@@ -866,7 +866,7 @@ void vtkWrapPython_GenerateSpecialType(
if (has_copycons)
{
fprintf(fp,
" PyVTKSpecialType_Add(\n"
" PyTypeObject *pytype = PyVTKSpecialType_Add(\n"
" &Py%s_Type,\n"
" Py%s_Methods,\n"
" Py%s_%*.*s_Methods,\n"
......@@ -879,7 +879,7 @@ void vtkWrapPython_GenerateSpecialType(
else if (constructor)
{
fprintf(fp,
" PyVTKSpecialType_Add(\n"
" PyTypeObject *pytype = PyVTKSpecialType_Add(\n"
" &Py%s_Type,\n"
" Py%s_Methods,\n"
" Py%s_%*.*s_Methods,\n"
......@@ -891,7 +891,7 @@ void vtkWrapPython_GenerateSpecialType(
else
{
fprintf(fp,
" PyVTKSpecialType_Add(\n"
" PyTypeObject *pytype = PyVTKSpecialType_Add(\n"
" &Py%s_Type,\n"
" Py%s_Methods,\n"
" nullptr,\n"
......@@ -900,10 +900,6 @@ void vtkWrapPython_GenerateSpecialType(
classname, classname);
}
fprintf(fp,
" PyTypeObject *pytype = &Py%s_Type;\n\n",
classname);
/* if type is already ready, then return */
fprintf(fp,
" if ((pytype->tp_flags & Py_TPFLAGS_READY) != 0)\n"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment