From 41c658017139d6a40d02c66c0074dc8e00f8d210 Mon Sep 17 00:00:00 2001
From: David Gobbi <david.gobbi@gmail.com>
Date: Sun, 26 Jul 2015 15:24:16 -0600
Subject: [PATCH] Make python enum type objects static.

This was the last generated type object that was exported.  Now that
it is static, the wrapper-specific import/export macros are no longer
needed.
---
 Wrapping/PythonCore/PyVTKObject.cxx   |   8 --
 Wrapping/PythonCore/vtkPythonArgs.cxx |  11 ++-
 Wrapping/PythonCore/vtkPythonArgs.h   |  12 +--
 Wrapping/Tools/vtkWrapPython.c        | 131 +-------------------------
 Wrapping/Tools/vtkWrapPythonClass.c   |   2 +-
 Wrapping/Tools/vtkWrapPythonEnum.c    |  56 +++++++++--
 Wrapping/Tools/vtkWrapPythonEnum.h    |   4 +
 Wrapping/Tools/vtkWrapPythonMethod.c  |   6 +-
 Wrapping/Tools/vtkWrapPythonType.c    |   2 +-
 9 files changed, 70 insertions(+), 162 deletions(-)

diff --git a/Wrapping/PythonCore/PyVTKObject.cxx b/Wrapping/PythonCore/PyVTKObject.cxx
index 7ae37fc70e6..5a19ea1b19c 100644
--- a/Wrapping/PythonCore/PyVTKObject.cxx
+++ b/Wrapping/PythonCore/PyVTKObject.cxx
@@ -39,14 +39,6 @@
 #include <vtksys/ios/sstream>
 #include <vtksys/cstddef>
 
-#if defined(VTK_BUILD_SHARED_LIBS)
-# define VTK_PYTHON_EXPORT VTK_ABI_EXPORT
-# define VTK_PYTHON_IMPORT VTK_ABI_IMPORT
-#else
-# define VTK_PYTHON_EXPORT VTK_ABI_EXPORT
-# define VTK_PYTHON_IMPORT VTK_ABI_EXPORT
-#endif
-
 // This will be set to the python type struct for vtkObjectBase
 static PyTypeObject *PyVTKObject_Type = 0;
 
diff --git a/Wrapping/PythonCore/vtkPythonArgs.cxx b/Wrapping/PythonCore/vtkPythonArgs.cxx
index 07f3d791ab1..80ab4820942 100644
--- a/Wrapping/PythonCore/vtkPythonArgs.cxx
+++ b/Wrapping/PythonCore/vtkPythonArgs.cxx
@@ -876,10 +876,10 @@ void *vtkPythonArgs::GetArgAsSpecialObject(
   return r;
 }
 
-int vtkPythonArgs::GetArgAsEnum(PyTypeObject *enumtype, bool &valid)
+int vtkPythonArgs::GetArgAsEnum(const char *enumname, bool &valid)
 {
   PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++);
-  int i = vtkPythonArgs::GetArgAsEnum(o, enumtype, valid);
+  int i = vtkPythonArgs::GetArgAsEnum(o, enumname, valid);
   if (!valid)
     {
     this->RefineArgTypeError(this->I - this->M - 1);
@@ -888,10 +888,11 @@ int vtkPythonArgs::GetArgAsEnum(PyTypeObject *enumtype, bool &valid)
 }
 
 int vtkPythonArgs::GetArgAsEnum(
-  PyObject *o, PyTypeObject *enumtype, bool &valid)
+  PyObject *o, const char *enumname, bool &valid)
 {
   long i = 0;
-  if (o->ob_type == enumtype)
+  PyTypeObject *pytype = vtkPythonUtil::FindEnum(enumname);
+  if (pytype && PyObject_TypeCheck(o, pytype))
     {
     i = PyInt_AsLong(o);
     valid = true;
@@ -899,7 +900,7 @@ int vtkPythonArgs::GetArgAsEnum(
   else
     {
     std::string errstring = "expected enum ";
-    errstring += enumtype->tp_name;
+    errstring += enumname;
     errstring += ", got ";
     errstring += o->ob_type->tp_name;
     PyErr_SetString(PyExc_TypeError, errstring.c_str());
diff --git a/Wrapping/PythonCore/vtkPythonArgs.h b/Wrapping/PythonCore/vtkPythonArgs.h
index 1b024555517..3f2d5d3d8d4 100644
--- a/Wrapping/PythonCore/vtkPythonArgs.h
+++ b/Wrapping/PythonCore/vtkPythonArgs.h
@@ -168,14 +168,14 @@ public:
   // Description:
   // Get the next argument as an enum value.
   template<class T>
-  bool GetEnumValue(T &v, PyTypeObject *enumtype) {
+  bool GetEnumValue(T &v, const char *enumname) {
     bool r;
-    v = static_cast<T>(this->GetArgAsEnum(enumtype, r));
+    v = static_cast<T>(this->GetArgAsEnum(enumname, r));
     return r; }
   template<class T>
-  static bool GetEnumValue(PyObject *o, T &v, PyTypeObject *enumtype) {
+  static bool GetEnumValue(PyObject *o, T &v, const char *enumname) {
     bool r;
-    v = static_cast<T>(vtkPythonArgs::GetArgAsEnum(o, enumtype, r));
+    v = static_cast<T>(vtkPythonArgs::GetArgAsEnum(o, enumname, r));
     return r; }
 
   // Description:
@@ -527,9 +527,9 @@ protected:
 
   // Description:
   // Get the next argument as an object of the given type.
-  int GetArgAsEnum(PyTypeObject *enumtype, bool &valid);
+  int GetArgAsEnum(const char *enumname, bool &valid);
   static int GetArgAsEnum(
-    PyObject *o, PyTypeObject *enumtype, bool &valid);
+    PyObject *o, const char *enumname, bool &valid);
 
   // Description:
   // Get the next argument as an object of the given type.
diff --git a/Wrapping/Tools/vtkWrapPython.c b/Wrapping/Tools/vtkWrapPython.c
index 1def4783a9a..32dd41e7609 100644
--- a/Wrapping/Tools/vtkWrapPython.c
+++ b/Wrapping/Tools/vtkWrapPython.c
@@ -273,121 +273,6 @@ static void vtkWrapPython_GenerateSpecialHeaders(
   free((char **)types);
 }
 
-/* -------------------------------------------------------------------- */
-/* import any wrapped enum types that are used by this file */
-static void vtkWrapPython_ImportExportEnumTypes(
-  FILE *fp, const char *thisModule,
-  FileInfo *file_info, HierarchyInfo *hinfo)
-{
-  const char **types;
-  int numTypes = 0;
-  FunctionInfo *currentFunction;
-  ClassInfo *data;
-  int i, j, k, n, m, ii, nn;
-  ValueInfo *val;
-
-  types = (const char **)malloc(1000*sizeof(const char *));
-
-  nn = file_info->Contents->NumberOfClasses;
-  for (ii = 0; ii < nn; ii++)
-    {
-    data = file_info->Contents->Classes[ii];
-    n = data->NumberOfFunctions;
-    for (i = 0; i < n; i++)
-      {
-      currentFunction = data->Functions[i];
-      if (currentFunction->Access == VTK_ACCESS_PUBLIC)
-        {
-        /* we start with the return value */
-        val = currentFunction->ReturnValue;
-        m = vtkWrap_CountWrappedParameters(currentFunction);
-
-        /* the -1 is for the return value */
-        for (j = (val ? -1 : 0); j < m; j++)
-          {
-          if (j >= 0)
-            {
-            val = currentFunction->Parameters[j];
-            }
-
-          if (vtkWrap_IsEnumMember(data, val))
-            {
-            /* enum is within the class namespace, no import needed */
-            val->IsEnum = 1;
-            }
-          else if (vtkWrapPython_IsEnumWrapped(hinfo, val->Class))
-            {
-            /* make a unique list of all enum types found */
-            val->IsEnum = 1;
-            for (k = 0; k < numTypes; k++)
-              {
-              if (strcmp(val->Class, types[k]) == 0)
-                {
-                break;
-                }
-              }
-            /* if not already in the list */
-            if (k == numTypes)
-              {
-              /* crude code to expand list as necessary */
-              if (numTypes > 0 && (numTypes % 1000) == 0)
-                {
-                types = (const char **)realloc((char **)types,
-                  (numTypes + 1000)*sizeof(const char *));
-                }
-              types[numTypes++] = val->Class;
-              }
-            }
-          }
-        }
-      }
-    }
-
-  /* for each unique enum type found in the file */
-  for (i = 0; i < numTypes; i++)
-    {
-    int is_external = 0;
-    const char *module;
-    char enumname[1000];
-    const char *cp = types[i];
-
-    /* convert "::" to an underscore */
-    j = 0;
-    while (*cp && j < 1000-1)
-      {
-      if (cp[0] == ':' && cp[1] == ':')
-        {
-        cp += 2;
-        enumname[j++] = '_';
-        }
-      else
-        {
-        enumname[j++] = *cp++;
-        }
-      }
-    enumname[j] = '\0';
-
-    /* check whether types is external or internal */
-    module = vtkWrapPython_ClassModule(hinfo, types[i]);
-    if (module && thisModule && strcmp(module, thisModule) != 0)
-      {
-      is_external = 1;
-      }
-
-    fprintf(fp,
-      "\n"
-      "#ifndef DECLARED_Py%s_Type\n"
-      "extern %s PyTypeObject Py%s_Type;\n"
-      "#define DECLARED_Py%s_Type\n"
-      "#endif\n",
-      enumname,
-      (is_external ? "VTK_PYTHON_IMPORT" : "VTK_PYTHON_EXPORT"),
-      enumname, enumname);
-    }
-
-  free((char **)types);
-}
-
 /* -------------------------------------------------------------------- */
 /* This is the main entry point for the python wrappers.  When called,
  * it will print the vtkXXPython.c file contents to "fp".  */
@@ -507,20 +392,10 @@ int main(int argc, char *argv[])
           "#include \"%s.h\"\n\n",
           name);
 
-  /* define import/export macros for use in wrapper code */
-  fprintf(fp,
-          "#if defined(VTK_BUILD_SHARED_LIBS)\n"
-          "# define VTK_PYTHON_EXPORT VTK_ABI_EXPORT\n"
-          "# define VTK_PYTHON_IMPORT VTK_ABI_IMPORT\n"
-          "#else\n"
-          "# define VTK_PYTHON_EXPORT VTK_ABI_EXPORT\n"
-          "# define VTK_PYTHON_IMPORT VTK_ABI_EXPORT\n"
-          "#endif\n\n");
-
   /* do the export of the main entry point */
   fprintf(fp,
           "extern \"C\" { %s void PyVTKAddFile_%s(PyObject *, const char *); }\n",
-          "VTK_PYTHON_EXPORT", name);
+          "VTK_ABI_EXPORT", name);
 
   /* get the module that is being wrapped */
   data = file_info->MainClass;
@@ -533,8 +408,8 @@ int main(int argc, char *argv[])
     module = vtkWrapPython_ClassModule(hinfo, data->Name);
     }
 
-  /* do the imports of any enum types that are used by methods */
-  vtkWrapPython_ImportExportEnumTypes(fp, module, file_info, hinfo);
+  /* Identify all enum types that are used by methods */
+  vtkWrapPython_MarkAllEnums(file_info->Contents, hinfo);
 
   /* Wrap any enum types defined in the global namespace */
   for (i = 0; i < contents->NumberOfEnums; i++)
diff --git a/Wrapping/Tools/vtkWrapPythonClass.c b/Wrapping/Tools/vtkWrapPythonClass.c
index 94209ceb0e4..f652e4048f6 100644
--- a/Wrapping/Tools/vtkWrapPythonClass.c
+++ b/Wrapping/Tools/vtkWrapPythonClass.c
@@ -313,7 +313,7 @@ static void vtkWrapPython_ExportVTKClass(
   fprintf(fp,
           "extern \"C\" { %s PyObject *Py%s_ClassNew(); }\n"
           "\n",
-          "VTK_PYTHON_EXPORT", classname);
+          "VTK_ABI_EXPORT", classname);
 
   /* declare the New methods for all the superclasses */
   supername = vtkWrapPython_GetSuperClass(data, hinfo);
diff --git a/Wrapping/Tools/vtkWrapPythonEnum.c b/Wrapping/Tools/vtkWrapPythonEnum.c
index fb186b456a2..aa7baeae5ab 100644
--- a/Wrapping/Tools/vtkWrapPythonEnum.c
+++ b/Wrapping/Tools/vtkWrapPythonEnum.c
@@ -15,6 +15,8 @@
 
 #include "vtkWrapPythonEnum.h"
 
+#include "vtkWrap.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -40,6 +42,49 @@ int vtkWrapPython_IsEnumWrapped(
   return rval;
 }
 
+/* -------------------------------------------------------------------- */
+/* find and mark all enum parameters by setting IsEnum=1 */
+void vtkWrapPython_MarkAllEnums(
+  NamespaceInfo *contents, HierarchyInfo *hinfo)
+{
+  FunctionInfo *currentFunction;
+  int i, j, n, m, ii, nn;
+  ClassInfo *data;
+  ValueInfo *val;
+
+  nn = contents->NumberOfClasses;
+  for (ii = 0; ii < nn; ii++)
+    {
+    data = contents->Classes[ii];
+    n = data->NumberOfFunctions;
+    for (i = 0; i < n; i++)
+      {
+      currentFunction = data->Functions[i];
+      if (currentFunction->Access == VTK_ACCESS_PUBLIC)
+        {
+        /* we start with the return value */
+        val = currentFunction->ReturnValue;
+        m = vtkWrap_CountWrappedParameters(currentFunction);
+
+        /* the -1 is for the return value */
+        for (j = (val ? -1 : 0); j < m; j++)
+          {
+          if (j >= 0)
+            {
+            val = currentFunction->Parameters[j];
+            }
+
+          if (vtkWrap_IsEnumMember(data, val) ||
+              vtkWrapPython_IsEnumWrapped(hinfo, val->Class))
+            {
+            val->IsEnum = 1;
+            }
+          }
+        }
+      }
+    }
+}
+
 /* -------------------------------------------------------------------- */
 /* generate a wrapped enum type */
 void vtkWrapPython_AddEnumType(
@@ -89,20 +134,11 @@ void vtkWrapPython_GenerateEnumType(
     sprintf(tpname, "%.200s", data->Name);
     }
 
-  /* forward declaration of the type object */
-  fprintf(fp,
-    "#ifndef DECLARED_Py%s_Type\n"
-    "extern %s PyTypeObject Py%s_Type;\n"
-    "#define DECLARED_Py%s_Type\n"
-    "#endif\n"
-    "\n",
-    enumname, "VTK_PYTHON_EXPORT", enumname, enumname);
-
   /* generate all functions and protocols needed for the type */
 
   /* generate the TypeObject */
   fprintf(fp,
-    "PyTypeObject Py%s_Type = {\n"
+    "static PyTypeObject Py%s_Type = {\n"
     "  PyObject_HEAD_INIT(&PyType_Type)\n"
     "  0,\n"
     "  \"%sPython.%s\", // tp_name\n"
diff --git a/Wrapping/Tools/vtkWrapPythonEnum.h b/Wrapping/Tools/vtkWrapPythonEnum.h
index b8b655e579d..951f84990a1 100644
--- a/Wrapping/Tools/vtkWrapPythonEnum.h
+++ b/Wrapping/Tools/vtkWrapPythonEnum.h
@@ -24,6 +24,10 @@
 int vtkWrapPython_IsEnumWrapped(
   HierarchyInfo *hinfo, const char *enumname);
 
+/* find and mark all enum parameters by setting IsEnum=1 */
+void vtkWrapPython_MarkAllEnums(
+  NamespaceInfo *contents, HierarchyInfo *hinfo);
+
 /* write out an enum type wrapped in python */
 void vtkWrapPython_GenerateEnumType(
   FILE *fp, const char *module, const char *classname, EnumInfo *data);
diff --git a/Wrapping/Tools/vtkWrapPythonMethod.c b/Wrapping/Tools/vtkWrapPythonMethod.c
index 02f0f4f0955..73663a36c7e 100644
--- a/Wrapping/Tools/vtkWrapPythonMethod.c
+++ b/Wrapping/Tools/vtkWrapPythonMethod.c
@@ -245,7 +245,7 @@ void vtkWrapPython_GetSingleArgument(
 
   if (vtkWrap_IsEnumMember(data, arg))
     {
-    fprintf(fp, "%sGetEnumValue(%stemp%d, &Py%s_%s_Type)",
+    fprintf(fp, "%sGetEnumValue(%stemp%d, \"%s.%s\")",
             prefix, argname, i, data->Name, arg->Class);
     }
   else if (arg->IsEnum)
@@ -257,12 +257,12 @@ void vtkWrapPython_GetSingleArgument(
       }
     if (cp[l] == ':' && cp[l+1] == ':')
       {
-      fprintf(fp, "%sGetEnumValue(%stemp%d, &Py%*.*s_%s_Type)",
+      fprintf(fp, "%sGetEnumValue(%stemp%d, \"%*.*s.%s\")",
               prefix, argname, i, (int)l, (int)l, cp, &cp[l+2]);
       }
     else
       {
-      fprintf(fp, "%sGetEnumValue(%stemp%d, &Py%s_Type)",
+      fprintf(fp, "%sGetEnumValue(%stemp%d, \"%s\")",
               prefix, argname, i, cp);
       }
     }
diff --git a/Wrapping/Tools/vtkWrapPythonType.c b/Wrapping/Tools/vtkWrapPythonType.c
index d920cbf0648..75116b3ae35 100644
--- a/Wrapping/Tools/vtkWrapPythonType.c
+++ b/Wrapping/Tools/vtkWrapPythonType.c
@@ -792,7 +792,7 @@ void vtkWrapPython_GenerateSpecialType(
   /* export New method for use by subclasses */
   fprintf(fp,
     "extern \"C\" { %s PyObject *Py%s_TypeNew(); }\n\n",
-    "VTK_PYTHON_EXPORT", classname);
+    "VTK_ABI_EXPORT", classname);
 
   /* import New method of the superclass */
   if (has_superclass)
-- 
GitLab