diff --git a/dtool/src/cppparser/cppBison.yxx b/dtool/src/cppparser/cppBison.yxx index cb5bca3524..be09b4e642 100644 --- a/dtool/src/cppparser/cppBison.yxx +++ b/dtool/src/cppparser/cppBison.yxx @@ -857,15 +857,15 @@ function_prototype: // As an added bonus, the type of the formal_parameter will be the // typecast type, i.e. the return type of the typecast function. - // We give all typecast operators the name "operator typecast". - // Only their return type will differentiate them. (Naturally, this - // violates actual C++ rules, but we're not an actual C++ compiler - // so we don't care. And this is the easiest way to do it.) + // We give typecast operators the name "operator typecast ", + // where is a simple name of the type to be typecast. Use + // the method's return type to determine the full type description. + string name = "operator typecast " + $2->get_simple_name(); CPPIdentifier *ident = $1; if (ident == NULL) { - ident = new CPPIdentifier("operator typecast", @1.file); + ident = new CPPIdentifier(name, @1.file); } else { - ident->add_name("operator typecast"); + ident->add_name(name); } $$ = CPPInstance::make_typecast_function (new CPPInstance($2, $3, 0, @3.file), ident, $6, $8); diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index b5bd404523..ca0c5bbb8e 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -98,6 +98,7 @@ RenameSet methodRenameDictionary[] = { { "operator ->" , "dereference", 0 }, { "operator <<=" , "__ilshift__", 1 }, { "operator >>=" , "__irshift__", 1 }, + { "operator typecast bool" , "__nonzero__", 0 }, { "print" , "Cprint", 0 }, { "CInterval.set_t" , "_priv__cSetT", 0 }, { NULL, NULL, -1 } @@ -206,7 +207,7 @@ std::string classNameFromCppName(const std::string &cppName) //# initialize to empty string std::string className = ""; //# These are the characters we want to strip out of the name - const std::string badChars("!@#$%^&*()<>,.-=+~{}? "); + const std::string badChars("!@#$%^&*()<>,.-=+~{}?"); int nextCap = 0; int firstChar = 1; for(std::string::const_iterator chr = cppName.begin(); chr != cppName.end(); chr++) @@ -214,7 +215,7 @@ std::string classNameFromCppName(const std::string &cppName) if (badChars.find(*chr) != std::string::npos) { } - else if (*chr == '_') + else if (*chr == '_' || *chr == ' ') { nextCap = 1; } @@ -271,14 +272,14 @@ std::string nonClassNameFromCppName(const std::string &cppName_in) /////////////////////////////////////////////////////////////////////////////////////// std::string methodNameFromCppName(const std::string &cppName, const std::string &className) { std::string methodName; - std::string badChars(" "); + const std::string badChars("!@#$%^&*()<>,.-=+~{}?"); int nextCap = 0; for(std::string::const_iterator chr = cppName.begin(); chr != cppName.end(); chr++) { if (badChars.find(*chr) != std::string::npos) { } - else if (*chr == '_') + else if (*chr == '_' || *chr == ' ') { nextCap = 1; } @@ -559,6 +560,16 @@ get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def) { return true; } + if (func->_ifunc.is_operator_typecast()) { + // A typecast operator. If it's a bool type, then we wrap it with + // the __nonzero__ slot method. + if (!func->_remaps.empty() && TypeManager::is_bool(func->_remaps[0]->_return_type->get_orig_type())) { + def._answer_location = "tp_as_number->nb_nonzero"; + def._wrapper_type = WT_inquiry; + return true; + } + } + return false; } @@ -1442,6 +1453,29 @@ write_module_class(ostream &out, Object *obj) { out << "}\n\n"; } break; + + case WT_inquiry: + // int func(PyObject *self) + { + Function *func = rfi->first; + out << "//////////////////\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions. \n"; + out << "// " <second._answer_location <<" = "<< methodNameFromCppName(func,export_calss_name) <<"\n"; + out << "//////////////////\n"; + out << "static int " << func->_name << methodNameFromCppName(func,export_calss_name) << "(PyObject *self)\n"; + out << "{\n"; + out << " PyObject *args = Py_BuildValue(\"()\");\n"; + out << " PyObject *result = " << func->_name <<"(self, args, NULL);\n"; + out << " Py_DECREF(args);\n"; + out << " if (result == NULL) {\n"; + out << " return -1;\n"; + out << " }\n"; + out << " int iresult = PyInt_AsLong(result);\n"; + out << " Py_DECREF(result);\n"; + out << " return iresult;\n"; + out << "}\n\n"; + } + break; case WT_none: break; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index 21f0d04b36..fe6cb5128b 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -73,6 +73,7 @@ private: WT_sequence_setitem, WT_sequence_size, WT_mapping_setitem, + WT_inquiry, }; class SlottedFunctionDef { diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx index 579993c88d..b2d7198f6b 100644 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ b/dtool/src/interrogate/interrogateBuilder.cxx @@ -1685,6 +1685,11 @@ get_function(CPPInstance *function, string description, ifunction->_flags |= InterrogateFunction::F_unary_op; } + if (ftype->_flags & CPPFunctionType::F_operator_typecast) { + // This is a special typecast operator. + ifunction->_flags |= InterrogateFunction::F_operator_typecast; + } + ifunction->_flags |= flags; ifunction->_instances->insert(InterrogateFunction::Instances::value_type(function_signature, function)); ifunction->_expression = expression; diff --git a/dtool/src/interrogatedb/interrogateFunction.I b/dtool/src/interrogatedb/interrogateFunction.I index 6f4135c899..0dc6f30ab1 100644 --- a/dtool/src/interrogatedb/interrogateFunction.I +++ b/dtool/src/interrogatedb/interrogateFunction.I @@ -57,6 +57,17 @@ is_unary_op() const { return (_flags & F_unary_op) != 0; } +//////////////////////////////////////////////////////////////////// +// Function: InterrogateFunction::is_operator_typecast +// Access: Public +// Description: Returns true if the function is a special typecast +// operator, like operator bool(). +//////////////////////////////////////////////////////////////////// +INLINE bool InterrogateFunction:: +is_operator_typecast() const { + return (_flags & F_operator_typecast) != 0; +} + //////////////////////////////////////////////////////////////////// // Function: InterrogateFunction::get_class // Access: Public diff --git a/dtool/src/interrogatedb/interrogateFunction.h b/dtool/src/interrogatedb/interrogateFunction.h index 8d95be97f1..676eb53cf7 100644 --- a/dtool/src/interrogatedb/interrogateFunction.h +++ b/dtool/src/interrogatedb/interrogateFunction.h @@ -39,6 +39,7 @@ public: INLINE bool is_virtual() const; INLINE bool is_method() const; INLINE bool is_unary_op() const; + INLINE bool is_operator_typecast() const; INLINE TypeIndex get_class() const; INLINE bool has_scoped_name() const; @@ -70,6 +71,7 @@ private: F_getter = 0x0010, F_setter = 0x0020, F_unary_op = 0x0040, + F_operator_typecast = 0x0080, }; int _flags;