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

Get python superclasses with import.

If superclasses are linked via import, then it is no longer necessary
for the dynamic linker to be able to find the superclass objects.
This adds flexibility to the way the wrappers can be packaged.
parent 5a623a62
......@@ -900,6 +900,86 @@ PyTypeObject *vtkPythonUtil::FindEnum(const char *name)
return pytype;
}
//--------------------------------------------------------------------
PyTypeObject *vtkPythonUtil::FindClassTypeObject(
const char *mod, const char *name)
{
for (int i = 0; i < 2; i++)
{
// see if the class is already loaded
PyVTKClass *info = vtkPythonUtil::FindClass(name);
if (info)
{
return info->py_type;
}
if (i == 0 && !vtkPythonUtil::LoadExtensionModule(mod))
{
break;
}
}
return nullptr;
}
//--------------------------------------------------------------------
PyTypeObject *vtkPythonUtil::FindSpecialTypeObject(
const char *mod, const char *name)
{
for (int i = 0; i < 2; i++)
{
// see if the class is already loaded
PyVTKSpecialType *info = vtkPythonUtil::FindSpecialType(name);
if (info)
{
return info->py_type;
}
if (i == 0 && !vtkPythonUtil::LoadExtensionModule(mod))
{
break;
}
}
return nullptr;
}
//--------------------------------------------------------------------
bool vtkPythonUtil::LoadExtensionModule(const char *name)
{
for (int i = 0; i < 2; i++)
{
PyObject *m;
if (i == 0)
{
// try absolute import of "name"
m = PyImport_ImportModule(name);
}
else
{
// try import from "vtk" package
PyObject *l = PyList_New(1);
PyObject *s = PyString_FromString(name);
PyList_SET_ITEM(l, 0, s);
m = PyImport_ImportModuleLevel("vtk", nullptr, nullptr, l, 0);
Py_DECREF(l);
}
if (m)
{
Py_DECREF(m);
return true;
}
else if (i < 1)
{
PyErr_Clear();
}
else
{
PyErr_Print();
}
}
return false;
}
//--------------------------------------------------------------------
// mangle a void pointer into a SWIG-style string
char *vtkPythonUtil::ManglePointer(const void *ptr, const char *type)
......
......@@ -181,6 +181,36 @@ public:
*/
static PyTypeObject *FindEnum(const char *name);
/**
* Find the PyTypeObject for a wrapped VTK class.
* This will call FindClass() first, and if the class is not found,
* it will try to load the module that the class is stored in.
* If it fails, then it will set an exception and return NULL.
*/
static PyTypeObject *FindClassTypeObject(
const char *mod, const char *name);
/**
* Find the PyTypeObject for a wrapped VTK type (non-vtkObject class).
* This will call FindSpecialType() first, and if the type is not found,
* it will try to load the module that the type is stored in.
* If it fails, then it will set an exception and return NULL.
*/
static PyTypeObject *FindSpecialTypeObject(
const char *mod, const char *name);
/**
* Try to load an extension module, by looking in all the usual places.
* On failure, this will raise an exception and return "false".
*/
static bool LoadExtensionModule(const char *name);
/**
* Utility function to build a docstring by concatenating a series
* of strings until a null string is found.
*/
static PyObject *BuildDocString(const char *docstring[]);
/**
* Utility function for creating SWIG-style mangled pointer string.
*/
......
......@@ -91,14 +91,14 @@ const char *vtkWrapPython_GetSuperClass(
/* -------------------------------------------------------------------- */
/* check whether the superclass of the specified class is wrapped */
int vtkWrapPython_HasWrappedSuperClass(
const char *vtkWrapPython_HasWrappedSuperClass(
HierarchyInfo *hinfo, const char *classname, int *is_external)
{
HierarchyEntry *entry;
const char *module;
const char *name;
const char *supername;
int result = 0;
const char *result = NULL;
int depth = 0;
if (is_external)
......@@ -108,14 +108,14 @@ int vtkWrapPython_HasWrappedSuperClass(
if (!hinfo)
{
return 0;
return result;
}
name = classname;
entry = vtkParseHierarchy_FindEntry(hinfo, name);
if (!entry)
{
return 0;
return result;
}
module = entry->Module;
......@@ -151,7 +151,7 @@ int vtkWrapPython_HasWrappedSuperClass(
}
else
{
result = 1;
result = entry->Module;
break;
}
}
......@@ -403,7 +403,9 @@ static void vtkWrapPython_GenerateObjectNew(
HierarchyInfo *hinfo, int class_has_new)
{
char superclassname[1024];
const char *supermodule;
const char *name;
int is_external;
int has_constants = 0;
int i;
......@@ -473,9 +475,21 @@ static void vtkWrapPython_GenerateObjectNew(
if (name)
{
vtkWrapText_PythonName(name, superclassname);
fprintf(fp,
" pytype->tp_base = (PyTypeObject *)Py%s_ClassNew();\n\n",
superclassname);
supermodule = vtkWrapPython_HasWrappedSuperClass(
hinfo, data->Name, &is_external);
if (!is_external) /* superclass is in the same module */
{
fprintf(fp,
" pytype->tp_base = (PyTypeObject *)Py%s_ClassNew();\n\n",
superclassname);
}
else /* superclass is in a different module */
{
fprintf(fp,
" pytype->tp_base = vtkPythonUtil::FindClassTypeObject(\n"
" \"%sPython\", \"%s\");\n\n",
supermodule, superclassname);
}
}
/* check if any constants need to be added to the class dict */
......
......@@ -30,8 +30,10 @@ int vtkWrapPython_WrapOneClass(
const char *vtkWrapPython_GetSuperClass(
ClassInfo *data, HierarchyInfo *hinfo);
/* check whether the superclass of the specified class is wrapped */
int vtkWrapPython_HasWrappedSuperClass(
/* check whether the superclass of the specified class is wrapped,
the module for the superclass is returned and is_external is
set if the module is different from ours */
const char *vtkWrapPython_HasWrappedSuperClass(
HierarchyInfo *hinfo, const char *classname, int *is_external);
/* generate the class docstring and write it to "fp" */
......
......@@ -665,6 +665,7 @@ void vtkWrapPython_GenerateSpecialType(
ClassInfo *data, FileInfo *finfo, HierarchyInfo *hinfo)
{
char supername[1024];
const char *supermodule;
const char *name;
SpecialTypeInfo info;
const char *constructor = NULL;
......@@ -683,10 +684,11 @@ void vtkWrapPython_GenerateSpecialType(
}
/* get the superclass */
has_superclass = vtkWrapPython_HasWrappedSuperClass(
supermodule = vtkWrapPython_HasWrappedSuperClass(
hinfo, data->Name, &is_external);
if (has_superclass)
if (supermodule)
{
has_superclass = 1;
name = vtkWrapPython_GetSuperClass(data, hinfo);
vtkWrapText_PythonName(name, supername);
}
......@@ -844,7 +846,7 @@ void vtkWrapPython_GenerateSpecialType(
"VTK_ABI_EXPORT", classname);
/* import New method of the superclass */
if (has_superclass)
if (has_superclass && !is_external)
{
fprintf(fp,
"#ifndef DECLARED_Py%s_TypeNew\n"
......@@ -912,9 +914,19 @@ void vtkWrapPython_GenerateSpecialType(
/* call the superclass New (initialize in dependency order) */
if (has_superclass)
{
fprintf(fp,
" pytype->tp_base = (PyTypeObject *)Py%s_TypeNew();\n\n",
supername);
if (!is_external) /* superclass is in the same module */
{
fprintf(fp,
" pytype->tp_base = (PyTypeObject *)Py%s_TypeNew();\n\n",
supername);
}
else /* superclass is in a different module */
{
fprintf(fp,
" pytype->tp_base = vtkPythonUtil::FindSpecialTypeObject(\n"
" \"%sPython\", \"%s\");\n\n",
supermodule, supername);
}
}
/* check whether the class has any constants as members */
......
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