diff --git a/direct/src/ffi/FFIInterrogateDatabase.py b/direct/src/ffi/FFIInterrogateDatabase.py index 86092be018..914bc3e87e 100644 --- a/direct/src/ffi/FFIInterrogateDatabase.py +++ b/direct/src/ffi/FFIInterrogateDatabase.py @@ -362,15 +362,23 @@ class FFIInterrogateDatabase: def constructClassTypeDescriptor(self, typeIndex): if self.isDefinedType(typeIndex): return self.typeIndexMap[typeIndex] + typeName = FFIRename.classNameFromCppName(getTypeName(typeIndex)) + if typeName == "PyObject": + # A special case: the PyObject type is really a native + # Python object, not to be molested--it's not really an + # FFI class object. + descriptor = FFITypes.PyObjectTypeDescriptor() + self.typeIndexMap[typeIndex] = descriptor + return descriptor + descriptor = FFITypes.ClassTypeDescriptor() self.typeIndexMap[typeIndex] = descriptor #descriptor.environment = self.environment - descriptor.foreignTypeName = FFIRename.classNameFromCppName(getTypeName(typeIndex)) + descriptor.foreignTypeName = typeName - if (descriptor.foreignTypeName == "TypedObject"): + if (typeName == "TypedObject"): print "Found typed object descriptor" FFITypes.TypedObjectDescriptor = descriptor - descriptor.isNested = interrogate_type_is_nested(typeIndex) if descriptor.isNested: diff --git a/direct/src/ffi/FFISpecs.py b/direct/src/ffi/FFISpecs.py index 2502a4a55e..91b5348146 100644 --- a/direct/src/ffi/FFISpecs.py +++ b/direct/src/ffi/FFISpecs.py @@ -47,7 +47,8 @@ class FunctionSpecification: indent(file, nesting, 'assert((isinstance(' + methodArgSpec.name + ', types.FloatType) or isinstance(' + methodArgSpec.name + ', types.IntType)))\n') - else: + + elif typeDesc.__class__ != FFITypes.PyObjectTypeDescriptor: # Get the real return type (not derived) if ((not typeDesc.isNested) and # Do not put our own module in the import list diff --git a/direct/src/ffi/FFITypes.py b/direct/src/ffi/FFITypes.py index 1c2f2ca14a..11f987e71c 100644 --- a/direct/src/ffi/FFITypes.py +++ b/direct/src/ffi/FFITypes.py @@ -108,6 +108,19 @@ class PrimitiveTypeDescriptor(BaseTypeDescriptor): """ indent(file, nesting, 'return returnValue\n') +class PyObjectTypeDescriptor(BaseTypeDescriptor): + """ + This is a special type descriptor for a PyObject * parameter, + which means a natural Python object of any type, to be passed + through without molestation. + """ + def __init__(self): + BaseTypeDescriptor.__init__(self) + + def generateReturnValueWrapper(self, classTypeDesc, file, userManagesMemory, + needsDowncast, nesting): + indent(file, nesting, 'return returnValue\n') + class EnumTypeDescriptor(PrimitiveTypeDescriptor): diff --git a/dtool/src/interrogate/interfaceMakerPython.cxx b/dtool/src/interrogate/interfaceMakerPython.cxx index 1d5fafad91..8b07daa34e 100644 --- a/dtool/src/interrogate/interfaceMakerPython.cxx +++ b/dtool/src/interrogate/interfaceMakerPython.cxx @@ -72,6 +72,12 @@ test_assert(ostream &out, int indent_level) const { << "return (PyObject *)NULL;\n"; indent(out, indent_level) << "}\n"; + indent(out, indent_level) + << "if (PyErr_Occurred()) {\n"; + indent(out, indent_level + 2) + << "return (PyObject *)NULL;\n"; + indent(out, indent_level) + << "}\n"; out << "#endif\n"; } } diff --git a/dtool/src/interrogate/interfaceMakerPythonSimple.cxx b/dtool/src/interrogate/interfaceMakerPythonSimple.cxx index e67cd33dc3..920b202200 100644 --- a/dtool/src/interrogate/interfaceMakerPythonSimple.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonSimple.cxx @@ -298,6 +298,12 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func, format_specifiers += "s"; parameter_list += ", &" + param_name; + } else if (TypeManager::is_pointer_to_PyObject(type)) { + out << "PyObject *" << param_name; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + pexpr_string = param_name; + } else if (TypeManager::is_pointer(type)) { out << "int " << param_name; format_specifiers += "i"; @@ -409,6 +415,10 @@ pack_return_value(ostream &out, int indent_level, indent(out, indent_level) << "return PyString_FromString(" << return_expr << ");\n"; + } else if (TypeManager::is_pointer_to_PyObject(type)) { + indent(out, indent_level) + << "return " << return_expr << ";\n"; + } else if (TypeManager::is_pointer(type)) { indent(out, indent_level) << "return PyInt_FromLong((int)" << return_expr << ");\n"; diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index 9c6e957fac..2ffc29819b 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -714,6 +714,44 @@ is_const_ref_to_pointer_to_base(CPPType *type) { } } +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::is_pointer_to_PyObject +// Access: Public, Static +// Description: Returns true if the indicated type is PyObject *. +//////////////////////////////////////////////////////////////////// +bool TypeManager:: +is_pointer_to_PyObject(CPPType *type) { + switch (type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_pointer_to_PyObject(type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_pointer: + return is_PyObject(type->as_pointer_type()->_pointing_at); + + default: + return false; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::is_PyObject +// Access: Public, Static +// Description: Returns true if the indicated type is PyObject. +//////////////////////////////////////////////////////////////////// +bool TypeManager:: +is_PyObject(CPPType *type) { + switch (type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_PyObject(type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_extension: + return (type->get_local_name(&parser) == "PyObject"); + + default: + return false; + } +} + //////////////////////////////////////////////////////////////////// // Function: TypeManager::involves_unpublished // Access: Public, Static diff --git a/dtool/src/interrogate/typeManager.h b/dtool/src/interrogate/typeManager.h index db68e30697..79a0438bfa 100644 --- a/dtool/src/interrogate/typeManager.h +++ b/dtool/src/interrogate/typeManager.h @@ -77,6 +77,8 @@ public: static bool is_pointer_to_base(CPPType *type); static bool is_const_pointer_to_base(CPPType *type); static bool is_const_ref_to_pointer_to_base(CPPType *type); + static bool is_pointer_to_PyObject(CPPType *type); + static bool is_PyObject(CPPType *type); static bool involves_unpublished(CPPType *type); static bool involves_protected(CPPType *type); diff --git a/dtool/src/parser-inc/Python.h b/dtool/src/parser-inc/Python.h new file mode 100755 index 0000000000..1b5316b7f2 --- /dev/null +++ b/dtool/src/parser-inc/Python.h @@ -0,0 +1,29 @@ +// Filename: Python.h +// Created by: drose (12May00) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +// This file, and all the other files in this directory, aren't +// intended to be compiled--they're just parsed by CPPParser (and +// interrogate) in lieu of the actual system headers, to generate the +// interrogate database. + +#ifndef PYTHON_H +#define PYTHON_H + +class PyObject; + +#endif // PYTHON_H diff --git a/dtool/src/parser-inc/Sources.pp b/dtool/src/parser-inc/Sources.pp index bf5027ac01..1c55be57de 100644 --- a/dtool/src/parser-inc/Sources.pp +++ b/dtool/src/parser-inc/Sources.pp @@ -2,4 +2,5 @@ algorithm deque ft2build.h iostream list map memory \ pair queue set stack stdcompare.h stdtypedefs.h \ string vector windows.h zlib.h md5.h files.h hex.h \ - nurbs.hh stddef.h krb5.h + nurbs.hh stddef.h krb5.h Python.h +