Commit 67a70a82 authored by David Gobbi's avatar David Gobbi

Allow use of all enum types as method parameters.

Previously, enum types could only be used as method parameters if
the enum type was defined in the same class as the method.  This change
removes that restriction, by using the hierarchy files to figure out
what enum types will be wrapped across the whole project.

Change-Id: Ia44272a341312f984d05ed54ae3318c12a2fe404
parent b271e764
......@@ -620,10 +620,29 @@ int vtkPythonOverload::CheckArg(
{
classname++;
}
if (PyInt_Check(arg) &&
strcmp(arg->ob_type->tp_name, classname) == 0)
if (PyInt_Check(arg))
{
penalty = VTK_PYTHON_EXACT_MATCH;
if (strcmp(arg->ob_type->tp_name, classname) == 0)
{
penalty = VTK_PYTHON_EXACT_MATCH;
}
else
{
/* tp_name doesn't include namespace, so we also allow
matches between "name" and "namespace.name" */
size_t l, m;
l = strlen(arg->ob_type->tp_name);
m = strlen(classname);
if (l < m && !isalnum(classname[m-l-1]) &&
strcmp(arg->ob_type->tp_name, &classname[m-l]) == 0)
{
penalty = VTK_PYTHON_GOOD_MATCH;
}
else
{
penalty = VTK_PYTHON_NEEDS_CONVERSION;
}
}
}
else
{
......
......@@ -23,6 +23,9 @@
#include "vtkParseMain.h"
#include "vtkParseExtras.h"
/* required for VTK_BUILD_SHARED_LIBS */
#include "vtkConfigure.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -41,6 +44,10 @@ void vtkParseOutput(FILE *fp, FileInfo *data);
static const char *vtkWrapPython_ClassHeader(
HierarchyInfo *hinfo, const char *classname);
/* get the module for the named VTK class */
static const char *vtkWrapPython_ClassModule(
HierarchyInfo *hinfo, const char *classname);
/* print out headers for any special types used by methods */
static void vtkWrapPython_GenerateSpecialHeaders(
FILE *fp, FileInfo *file_info, HierarchyInfo *hinfo);
......@@ -125,6 +132,26 @@ static const char *vtkWrapPython_ClassHeader(
return 0;
}
/* -------------------------------------------------------------------- */
/* Get the module for the specified class */
static const char *vtkWrapPython_ClassModule(
HierarchyInfo *hinfo, const char *classname)
{
HierarchyEntry *entry;
/* if "hinfo" is present, use it to find the file */
if (hinfo)
{
entry = vtkParseHierarchy_FindEntry(hinfo, classname);
if (entry)
{
return entry->Module;
}
}
return 0;
}
/* -------------------------------------------------------------------- */
/* generate includes for any special types that are used */
static void vtkWrapPython_GenerateSpecialHeaders(
......@@ -149,7 +176,7 @@ static void vtkWrapPython_GenerateSpecialHeaders(
for (i = 0; i < n; i++)
{
currentFunction = data->Functions[i];
if (vtkWrapPython_MethodCheck(data, currentFunction, hinfo))
if (currentFunction->Access == VTK_ACCESS_PUBLIC)
{
classname = "void";
aType = VTK_PARSE_VOID;
......@@ -249,6 +276,135 @@ static void vtkWrapPython_GenerateSpecialHeaders(
free((char **)types);
}
/* -------------------------------------------------------------------- */
/* import any wrapped enum types that are used by this file */
static void vtkWrapPython_ImportExportEnumTypes(
FILE *fp, FileInfo *file_info, HierarchyInfo *hinfo)
{
const char **types;
int numTypes = 0;
FunctionInfo *currentFunction;
const char *thisModule = 0;
int i, j, k, n, m, ii, nn;
ClassInfo *data;
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;
}
}
}
}
}
}
/* get the module that is being wrapped */
data = file_info->MainClass;
if (!data && file_info->Contents->NumberOfClasses > 0)
{
data = file_info->Contents->Classes[0];
}
if (data)
{
thisModule = vtkWrapPython_ClassModule(hinfo, data->Name);
}
/* 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,
#if defined(VTK_BUILD_SHARED_LIBS)
(is_external ? "VTK_ABI_IMPORT" : "VTK_ABI_EXPORT"),
#else
"VTK_ABI_EXPORT",
#endif
enumname, enumname);
}
free((char **)types);
}
/* -------------------------------------------------------------------- */
/* This is the main entry point for the python wrappers. When called,
......@@ -367,6 +523,9 @@ int main(int argc, char *argv[])
"extern \"C\" { %s void PyVTKAddFile_%s(PyObject *, const char *); }\n",
"VTK_ABI_EXPORT", name);
/* do the imports of any enum types that are used by methods */
vtkWrapPython_ImportExportEnumTypes(fp, file_info, hinfo);
/* Wrap any enum types defined in the global namespace */
for (i = 0; i < contents->NumberOfEnums; i++)
{
......
......@@ -20,6 +20,28 @@
#include <string.h>
#include <ctype.h>
/* -------------------------------------------------------------------- */
/* check whether an enum type will be wrapped */
int vtkWrapPython_IsEnumWrapped(
HierarchyInfo *hinfo, const char *enumname)
{
int rval = 0;
HierarchyEntry *entry;
if (hinfo && enumname)
{
entry = vtkParseHierarchy_FindEntry(hinfo, enumname);
if (entry && entry->IsEnum)
{
rval = 1;
}
}
return rval;
}
/* -------------------------------------------------------------------- */
/* generate a wrapped enum type */
void vtkWrapPython_AddEnumType(
FILE *fp, const char *indent, const char *dictvar, const char *objvar,
const char *scope, EnumInfo *cls)
......
......@@ -20,6 +20,10 @@
#include "vtkParseData.h"
#include "vtkParseHierarchy.h"
/* check whether an enum type will be wrapped */
int vtkWrapPython_IsEnumWrapped(
HierarchyInfo *hinfo, const char *enumname);
/* write out an enum type wrapped in python */
void vtkWrapPython_GenerateEnumType(
FILE *fp, const char *classname, EnumInfo *data);
......
......@@ -231,8 +231,10 @@ void vtkWrapPython_GetSingleArgument(
FILE *fp, ClassInfo *data, int i, ValueInfo *arg, int static_call)
{
const char *prefix = "ap.";
const char *cp;
char argname[32];
char pythonname[1024];
size_t l;
argname[0] = '\0';
if (static_call)
......@@ -246,6 +248,24 @@ void vtkWrapPython_GetSingleArgument(
fprintf(fp, "%sGetEnumValue(%stemp%d, &Py%s_%s_Type)",
prefix, argname, i, data->Name, arg->Class);
}
else if (arg->IsEnum)
{
cp = arg->Class;
for (l = 0; cp[l] != '\0'; l++)
{
if (cp[l] == ':') { break; }
}
if (cp[l] == ':' && cp[l+1] == ':')
{
fprintf(fp, "%sGetEnumValue(%stemp%d, &Py%*.*s_%s_Type)",
prefix, argname, i, (int)l, (int)l, cp, &cp[l+2]);
}
else
{
fprintf(fp, "%sGetEnumValue(%stemp%d, &Py%s_Type)",
prefix, argname, i, cp);
}
}
else if (vtkWrap_IsPythonObject(arg))
{
fprintf(fp, "%s%sGetPythonObject(temp%d)",
......
......@@ -505,6 +505,7 @@ static int vtkWrapPython_IsValueWrappable(
if (vtkWrap_IsScalar(val))
{
if (vtkWrap_IsNumeric(val) ||
val->IsEnum || /* marked as enum in ImportExportEnumTypes */
vtkWrap_IsEnumMember(data, val) ||
vtkWrap_IsString(val))
{
......
......@@ -36,12 +36,14 @@ void vtkWrapPython_PythonicName(const char *name, char *pname)
{
size_t j = 0;
size_t i;
size_t l;
char *cp;
int scoped = 0;
/* look for first char that is not alphanumeric or underscore */
i = vtkParse_IdentifierLength(name);
l = vtkParse_IdentifierLength(name);
if (name[i] != '\0')
if (name[l] != '\0')
{
/* get the mangled name */
vtkParse_MangledTypeName(name, pname);
......@@ -51,6 +53,7 @@ void vtkWrapPython_PythonicName(const char *name, char *pname)
cp = pname;
while (*cp == 'N')
{
scoped++;
cp++;
while (*cp >= '0' && *cp <= '9')
{
......@@ -86,6 +89,16 @@ void vtkWrapPython_PythonicName(const char *name, char *pname)
{
strcpy(pname, name);
}
/* remove the "_E" that is added to mangled scoped names */
if (scoped)
{
j = strlen(pname);
if (j > 2 && pname[j-2] == '_' && pname[j-1] == 'E')
{
pname[j-2] = '\0';
}
}
}
/* -------------------------------------------------------------------- */
......
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