diff --git a/dtool/src/dtoolbase/dtoolbase.h b/dtool/src/dtoolbase/dtoolbase.h index 7aaec2c1ce..160128e22e 100644 --- a/dtool/src/dtoolbase/dtoolbase.h +++ b/dtool/src/dtoolbase/dtoolbase.h @@ -23,7 +23,7 @@ #include "dtool_config.h" /* Make sure WIN32 and WIN32_VC are defined when using MSVC */ -#ifdef _WIN32 +#if defined(_WIN32) || defined(_WIN64) #ifndef WIN32 #define WIN32 #endif @@ -411,11 +411,6 @@ #define MAKE_SEQ(seq_name, num_name, element_name) #define EXTENSION(x) #define EXTEND -/* If you change these, don't forget to also change it in interrogate itself. */ -#define _EXT_FUNC(func) _ext__ ## func -#define EXT_FUNC(func) _EXT_FUNC(func) () -#define EXT_FUNC_ARGS(func, ...) _EXT_FUNC(func) (__VA_ARGS__) -#define CALL_EXT_FUNC(func, ...) _EXT_METHOD(cl, m) (__VA_ARGS__) #endif #ifdef __cplusplus diff --git a/dtool/src/dtoolbase/dtoolbase_cc.h b/dtool/src/dtoolbase/dtoolbase_cc.h index 494d92ea55..ad9e9897dd 100644 --- a/dtool/src/dtoolbase/dtoolbase_cc.h +++ b/dtool/src/dtoolbase/dtoolbase_cc.h @@ -220,32 +220,16 @@ private: #endif // USE_TAU -#ifdef CPPPARSER -#define EXT_METHOD(cl, m) cl::m() -#define EXT_METHOD_ARGS(cl, m, ...) cl::m(__VA_ARGS__) -#define EXT_CONST_METHOD(cl, m) cl::m() const -#define EXT_CONST_METHOD_ARGS(cl, m, ...) cl::m(__VA_ARGS__) const -#define EXT_NESTED_METHOD(cl1, cl2, m) cl1::cl2::m() -#define EXT_NESTED_METHOD_ARGS(cl1, cl2, m, ...) cl1::cl2::m(__VA_ARGS__) -#define EXT_NESTED_CONST_METHOD(cl1, cl2, m) cl1::cl2::m() const -#define EXT_NESTED_CONST_METHOD_ARGS(cl1, cl2, m, ...) cl1::cl2::m(__VA_ARGS__) const -#define CALL_EXT_METHOD(cl, m, obj, ...) (obj)-> m(__VA_ARGS__) -#else -/* If you change these, don't forget to also change it in interrogate itself. */ -#define __EXT_METHOD(cl, m) _ext_ ## cl ## _ ## m -#define _EXT_METHOD(cl, m) __EXT_METHOD(cl, m) -#define __EXT_NEST(cl1, cl2) cl1 ## __ ## cl2 -#define _EXT_NEST(cl1, cl2) __EXT_NEST(cl1, cl2) -#define EXT_METHOD(cl, m) _EXT_METHOD(cl, m) (cl * _ext_this) -#define EXT_METHOD_ARGS(cl, m, ...) _EXT_METHOD(cl, m) (cl * _ext_this, __VA_ARGS__) -#define EXT_CONST_METHOD(cl, m) _EXT_METHOD(cl, m) (const cl * _ext_this) -#define EXT_CONST_METHOD_ARGS(cl, m, ...) _EXT_METHOD(cl, m) (const cl * _ext_this, __VA_ARGS__) -#define EXT_NESTED_METHOD(cl1, cl2, m) _EXT_METHOD(_EXT_NEST(cl1, cl2), m) (cl1::cl2 * _ext_this) -#define EXT_NESTED_METHOD_ARGS(cl1, cl2, m, ...) _EXT_METHOD(_EXT_NEST(cl1, cl2), m) (cl1::cl2 * _ext_this, __VA_ARGS__) -#define EXT_NESTED_CONST_METHOD(cl1, cl2, m) _EXT_METHOD(_EXT_NEST(cl1, cl2), m) (const cl1::cl2 * _ext_this) -#define EXT_NESTED_CONST_METHOD_ARGS(cl1, cl2, m, ...) _EXT_METHOD(_EXT_NEST(cl1, cl2), m) (const cl1::cl2 * _ext_this, __VA_ARGS__) -#define CALL_EXT_METHOD(cl, m, ...) _EXT_METHOD(cl, m) (__VA_ARGS__) -#endif +// Macros from hell. +#define EXT_METHOD(cl, m) Extension::m() +#define EXT_METHOD_ARGS(cl, m, ...) Extension::m(__VA_ARGS__) +#define EXT_CONST_METHOD(cl, m) Extension::m() const +#define EXT_CONST_METHOD_ARGS(cl, m, ...) Extension::m(__VA_ARGS__) const +#define EXT_NESTED_METHOD(cl1, cl2, m) Extension::m() +#define EXT_NESTED_METHOD_ARGS(cl1, cl2, m, ...) Extension::m(__VA_ARGS__) +#define EXT_NESTED_CONST_METHOD(cl1, cl2, m) Extension::m() const +#define EXT_NESTED_CONST_METHOD_ARGS(cl1, cl2, m, ...) Extension::m(__VA_ARGS__) const +#define CALL_EXT_METHOD(cl, m, obj, ...) invoke_extension(obj).m(__VA_ARGS__) #endif // __cplusplus #endif diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index aa75f94934..b6bae90ab7 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -244,8 +244,12 @@ string FunctionRemap::call_function(ostream &out, int indent_level, bool convert // comment. //////////////////////////////////////////////////////////////////// void FunctionRemap:: -write_orig_prototype(ostream &out, int indent_level) const { - _cppfunc->output(out, indent_level, &parser, false, _num_default_parameters); +write_orig_prototype(ostream &out, int indent_level, bool local) const { + if (local) { + _cppfunc->output(out, indent_level, NULL, false, _num_default_parameters); + } else { + _cppfunc->output(out, indent_level, &parser, false, _num_default_parameters); + } } //////////////////////////////////////////////////////////////////// @@ -392,28 +396,13 @@ get_call_str(const string &container, const vector_string &pexprs) const { const char *separator = ""; // If this function is marked as having an extension function, - // call that instead. The naming convention of the extension - // function has to match the EXT_IMPL definition in dtoolbase.h. - if (_extension) { - if (_cpptype != NULL) { - // Fix nested classes by replacing :: with __ - char* nested_name = strdup(_cpptype->get_local_name(&parser).c_str()); - for (size_t i = 0; i < strlen(nested_name); ++i) { - if (nested_name[i] == ':') { - nested_name[i] = '_'; - } - } - call << "_ext_" << nested_name << "_" - << _cppfunc->get_local_name() << "("; - delete[] nested_name; - } else { - call << "_ext__" << _cppfunc->get_local_name() << "("; - } + // call that instead. + if (_extension && !container.empty()) { + call << "invoke_extension(" << container << ")."; + + call << _cppfunc->get_local_name(); + call << "("; - if (_has_this && !container.empty()) { - call << container; - separator = ", "; - } } else { if (_type == T_constructor) { @@ -569,11 +558,13 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak if (param._remap == (ParameterRemap *)NULL) { // If we can't handle one of the parameter types, we can't call // the function. + //nout << "Can't handle parameter " << i << " of method " << *_cppfunc << "\n"; return false; } param._remap->set_default_value(params[i]->_initializer); if (!param._remap->is_valid()) { + nout << "Invalid remap for parameter " << i << " of method " << *_cppfunc << "\n"; return false; } @@ -693,6 +684,31 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak // It receives no parameters, and returns a pointer. _flags |= F_make_copy; } + + } else if (fname == "__iter__" ) { + if (_has_this && _parameters.size() == 1 && + TypeManager::is_pointer(_return_type->get_new_type())) { + // It receives no parameters, and returns a pointer. + _flags |= F_iter; + } + + } else if (fname == "__getbuffer__" ) { + if (_has_this && _parameters.size() == 4 && + TypeManager::is_integer(_return_type->get_new_type()) && + TypeManager::is_pointer_to_PyObject(_parameters[1]._remap->get_orig_type()) && + TypeManager::is_pointer_to_Py_buffer(_parameters[2]._remap->get_orig_type()) && + TypeManager::is_integer(_parameters[3]._remap->get_orig_type())) { + + _flags |= F_getbuffer; + } + + } else if (fname == "__releasebuffer__" ) { + if (_has_this && _parameters.size() == 3 && + TypeManager::is_pointer_to_PyObject(_parameters[1]._remap->get_orig_type()) && + TypeManager::is_pointer_to_Py_buffer(_parameters[2]._remap->get_orig_type())) { + + _flags |= F_releasebuffer; + } } } else if (_type == T_constructor) { @@ -709,25 +725,21 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak return true; } - /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -std::string make_safe_name(const std::string & name) -{ - return InterrogateBuilder::clean_identifier(name); +std::string make_safe_name(const std::string &name) { + return InterrogateBuilder::clean_identifier(name); + /* + static const char safe_chars2[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; + std::string result = name; - /* - static const char safe_chars2[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; - std::string result = name; + size_t pos = result.find_first_not_of(safe_chars2); + while (pos != std::string::npos) { + result[pos] = '_'; + pos = result.find_first_not_of(safe_chars2); + } - size_t pos = result.find_first_not_of(safe_chars2); - while (pos != std::string::npos) - { - result[pos] = '_'; - pos = result.find_first_not_of(safe_chars2); - } - - return result; - */ + return result; + */ } diff --git a/dtool/src/interrogate/functionRemap.h b/dtool/src/interrogate/functionRemap.h index 644693bd9b..7ab8224ad1 100644 --- a/dtool/src/interrogate/functionRemap.h +++ b/dtool/src/interrogate/functionRemap.h @@ -56,7 +56,7 @@ public: bool convert_result, const string &container, const vector_string &pexprs = vector_string()) const; - void write_orig_prototype(ostream &out, int indent_level) const; + void write_orig_prototype(ostream &out, int indent_level, bool local=false) const; FunctionWrapperIndex make_wrapper_entry(FunctionIndex function_index); @@ -87,6 +87,9 @@ public: F_make_copy = 0x0020, F_copy_constructor = 0x0040, F_explicit_self = 0x0080, + F_iter = 0x0100, + F_getbuffer = 0x0200, + F_releasebuffer = 0x0400, }; typedef vector Parameters; diff --git a/dtool/src/interrogate/interfaceMaker.cxx b/dtool/src/interrogate/interfaceMaker.cxx index 32d510aff2..82185500b5 100644 --- a/dtool/src/interrogate/interfaceMaker.cxx +++ b/dtool/src/interrogate/interfaceMaker.cxx @@ -40,8 +40,7 @@ #include "cppStructType.h" #include "pnotify.h" - InterrogateType dummy_type; - +InterrogateType dummy_type; //////////////////////////////////////////////////////////////////// // Function: InterfaceMaker::Function::Constructor @@ -152,6 +151,10 @@ check_protocols() { _protocol_types |= PT_copy_constructor; } + if (flags & FunctionRemap::F_iter) { + _protocol_types |= PT_iter; + } + // Now are there any make_seq requests within this class? CPPStructType *stype = _itype._cpptype->as_struct_type(); if (stype != (CPPStructType *)NULL) { @@ -361,10 +364,9 @@ write_functions(ostream &out) { // support a module file. //////////////////////////////////////////////////////////////////// void InterfaceMaker:: -write_module(ostream &, ostream *out_h,InterrogateModuleDef *) { +write_module(ostream &, ostream *out_h, InterrogateModuleDef *) { } - //////////////////////////////////////////////////////////////////// // Function: InterfaceMaker::remap_parameter // Access: Public, Virtual @@ -379,6 +381,8 @@ write_module(ostream &, ostream *out_h,InterrogateModuleDef *) { //////////////////////////////////////////////////////////////////// ParameterRemap *InterfaceMaker:: remap_parameter(CPPType *struct_type, CPPType *param_type) { + nassertr(param_type != NULL, NULL); + if (convert_strings) { if (TypeManager::is_char_pointer(param_type)) { return new ParameterRemapCharStarToString(param_type); diff --git a/dtool/src/interrogate/interfaceMaker.h b/dtool/src/interrogate/interfaceMaker.h index 3f43a9772e..57e73ae008 100644 --- a/dtool/src/interrogate/interfaceMaker.h +++ b/dtool/src/interrogate/interfaceMaker.h @@ -115,6 +115,7 @@ public: PT_mapping = 0x0002, PT_make_copy = 0x0004, PT_copy_constructor = 0x0008, + PT_iter = 0x0010, }; int _protocol_types; }; diff --git a/dtool/src/interrogate/interfaceMakerPython.cxx b/dtool/src/interrogate/interfaceMakerPython.cxx index ec464e58ec..b1b5596fcd 100644 --- a/dtool/src/interrogate/interfaceMakerPython.cxx +++ b/dtool/src/interrogate/interfaceMakerPython.cxx @@ -15,7 +15,6 @@ #include "interfaceMakerPython.h" #include "interrogate.h" - //////////////////////////////////////////////////////////////////// // Function: InterfaceMakerPython::Constructor // Access: Public diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index a59984c62c..1efbfe6194 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -9,6 +9,7 @@ // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// + #include "interfaceMakerPythonNative.h" #include "interrogateBuilder.h" #include "interrogate.h" @@ -104,6 +105,9 @@ RenameSet methodRenameDictionary[] = { { "CInterval.set_t", "_priv__cSetT", 0 }, { "__bool__" , "__bool__", 0 }, { "__bytes__" , "__bytes__", 0 }, + { "__iter__" , "__iter__", 0 }, + { "__getbuffer__" , "__getbuffer__", 0 }, + { "__releasebuffer__", "__releasebuffer__", 0 }, { NULL, NULL, -1 } }; @@ -271,10 +275,11 @@ methodNameFromCppName(const std::string &cppName, const std::string &className, } if (className.size() > 0) { - string LookUpName = className + '.' + cppName; + string lookup_name = className + '.' + cppName; for (int x = 0; classRenameDictionary[x]._from != NULL; x++) { - if (LookUpName == methodRenameDictionary[x]._from) + if (lookup_name == methodRenameDictionary[x]._from) { methodName = methodRenameDictionary[x]._to; + } } } @@ -283,13 +288,12 @@ methodNameFromCppName(const std::string &cppName, const std::string &className, return methodName; } -std::string methodNameFromCppName(InterfaceMaker::Function *func, const std::string &className, bool mangle) -{ - std::string cppName = func->_ifunc.get_name(); - if (func->_ifunc.is_unary_op()) { - cppName += "unary"; - } - return methodNameFromCppName(cppName, className, mangle); +std::string methodNameFromCppName(InterfaceMaker::Function *func, const std::string &className, bool mangle) { + std::string cppName = func->_ifunc.get_name(); + if (func->_ifunc.is_unary_op()) { + cppName += "unary"; + } + return methodNameFromCppName(cppName, className, mangle); } /////////////////////////////////////////////////////////////////////////////////////// @@ -486,6 +490,20 @@ get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def) { } } + if (obj->_protocol_types & Object::PT_iter) { + if (method_name == "__iter__") { + def._answer_location = "tp_iter"; + def._wrapper_type = WT_no_params; + return true; + } + + if (method_name == "next") { + def._answer_location = "tp_iternext"; + def._wrapper_type = WT_no_params; + return true; + } + } + if (method_name == "operator ()") { def._answer_location = "tp_call"; def._wrapper_type = WT_none; @@ -518,6 +536,18 @@ get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def) { return true; } + if (method_name == "__getbuffer__") { + def._answer_location = "tp_as_buffer->bf_getbuffer"; + def._wrapper_type = WT_getbuffer; + return true; + } + + if (method_name == "__releasebuffer__") { + def._answer_location = "tp_as_buffer->bf_releasebuffer"; + def._wrapper_type = WT_releasebuffer; + return true; + } + if (func->_ifunc.is_operator_typecast()) { // A typecast operator. Check for a supported low-level typecast type. if (!func->_remaps.empty()) { @@ -549,7 +579,7 @@ get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def) { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: -GetValideChildClasses(std::map &answer, CPPStructType *inclass, const std::string &up_cast_seed, bool downcastposible) { +get_valid_child_classes(std::map &answer, CPPStructType *inclass, const std::string &upcast_seed, bool can_downcast) { if (inclass == NULL) { return; } @@ -561,13 +591,13 @@ GetValideChildClasses(std::map &answer, CPPStructType const CPPStructType::Base &base = (*bi); // if (base._vis <= V_public) -// downcastposible = false; +// can_downcast = false; CPPStructType *base_type = TypeManager::resolve_type(base._base)->as_struct_type(); if (base_type != NULL) { std::string scoped_name = base_type->get_local_name(&parser); if (answer.find(scoped_name) == answer.end()) { - answer[scoped_name]._can_downcast = downcastposible; + answer[scoped_name]._can_downcast = can_downcast; answer[scoped_name]._to_class_name = scoped_name; answer[scoped_name]._structType = base_type; @@ -575,41 +605,49 @@ GetValideChildClasses(std::map &answer, CPPStructType answer[scoped_name]._can_downcast = false; } - std::string local_up_cast("("); - local_up_cast += scoped_name + " *)"+ up_cast_seed +""; - answer[scoped_name]._up_cast_string = local_up_cast; - answer[scoped_name]._is_legal_py_class = isCppTypeLegal(base_type); + std::string local_upcast("("); + local_upcast += scoped_name + " *)"+ upcast_seed +""; + answer[scoped_name]._up_cast_string = local_upcast; + answer[scoped_name]._is_legal_py_class = is_cpp_type_legal(base_type); } else { answer[scoped_name]._can_downcast = false; } - GetValideChildClasses(answer,base_type, answer[scoped_name]._up_cast_string,answer[scoped_name]._can_downcast); + get_valid_child_classes(answer, base_type, answer[scoped_name]._up_cast_string, answer[scoped_name]._can_downcast); } } } + /////////////////////////////////////////////////////////////////////////////// -// Function : WriteReturnInstance +// Function : write_python_instance // /////////////////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: -WriteReturnInstance(ostream &out, int indent_level, std::string &return_expr, std::string &owns_memory_flag, const std::string &class_name, CPPType *ctype, bool inplace, const std::string &const_flag) { - if (inplace == true) { +write_python_instance(ostream &out, int indent_level, const std::string &return_expr, const std::string &assign_to, std::string &owns_memory_flag, const std::string &class_name, CPPType *ctype, bool inplace, const std::string &const_flag) { + string assign_stmt("return "); + if (!assign_to.empty()) { + assign_stmt = assign_to + " = "; + } + + if (inplace) { indent(out, indent_level) << "Py_INCREF(self);\n"; - indent(out, indent_level) << "return self;\n"; + indent(out, indent_level) << assign_stmt << "self;\n"; } else { - indent(out, indent_level) << "if (" << return_expr<< " == NULL) {\n"; + indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "}\n"; + indent(out, indent_level+2) << assign_stmt << "Py_None;\n"; + indent(out, indent_level) << "} else {\n"; if (IsPandaTypedObject(ctype->as_struct_type())) { std::string typestr = "(" + return_expr + ")->as_typed_object()->get_type_index()"; - indent(out, indent_level) << "return DTool_CreatePyInstanceTyped((void *)" << return_expr << ", " << CLASS_PREFIX << make_safe_name(class_name) << ", " << owns_memory_flag << ", " << const_flag << ", " << typestr << ");\n"; + indent(out, indent_level+2) << assign_stmt + << "DTool_CreatePyInstanceTyped((void *)" << return_expr << ", " << CLASS_PREFIX << make_safe_name(class_name) << ", " << owns_memory_flag << ", " << const_flag << ", " << typestr << ");\n"; } else { // indent(out, indent_level) << "if (" << return_expr << "!= NULL)\n"; - indent(out, indent_level) - << "return DTool_CreatePyInstance((void *)" << return_expr << ", " << CLASS_PREFIX << make_safe_name(class_name) << ", " << owns_memory_flag << ", " << const_flag << ");\n"; + indent(out, indent_level+2) << assign_stmt + << "DTool_CreatePyInstance((void *)" << return_expr << ", " << CLASS_PREFIX << make_safe_name(class_name) << ", " << owns_memory_flag << ", " << const_flag << ");\n"; } + indent(out, indent_level) << "}\n"; } } //////////////////////////////////////////////////////////////////// @@ -639,7 +677,8 @@ InterfaceMakerPythonNative:: // corresponding to the functions that will be output in // write_functions(). //////////////////////////////////////////////////////////////////// -void InterfaceMakerPythonNative::write_prototypes(ostream &out_code, ostream *out_h) { +void InterfaceMakerPythonNative:: +write_prototypes(ostream &out_code, ostream *out_h) { inside_python_native = true; Functions::iterator fi; @@ -656,7 +695,7 @@ void InterfaceMakerPythonNative::write_prototypes(ostream &out_code, ostream *ou for (fi = _functions.begin(); fi != _functions.end(); ++fi) { Function *func = (*fi); - if (!func->_itype.is_global() && isFunctionLegal(func)) + if (!func->_itype.is_global() && is_function_legal(func)) write_prototype_for (out_code, func); } */ @@ -665,11 +704,11 @@ void InterfaceMakerPythonNative::write_prototypes(ostream &out_code, ostream *ou for (oi = _objects.begin(); oi != _objects.end(); ++oi) { Object *object = (*oi).second; if (object->_itype.is_class() || object->_itype.is_struct()) { - if (isCppTypeLegal(object->_itype._cpptype)) { + if (is_cpp_type_legal(object->_itype._cpptype)) { if (isExportThisRun(object->_itype._cpptype)) { write_prototypes_class(out_code, out_h, object); } else { - //write_prototypes_class_external(out_code,object); + //write_prototypes_class_external(out_code, object); _external_imports.insert(make_safe_name(object->_itype.get_scoped_name())); } } @@ -686,27 +725,28 @@ void InterfaceMakerPythonNative::write_prototypes(ostream &out_code, ostream *ou inside_python_native = false; } + ///////////////////////////////////////////////////////////////////////////////////////////// // Function : write_prototypes_class_external // // Description : Output enough enformation to a declartion of a externally // generated dtool type object ///////////////////////////////////////////////////////////////////////////////////////////// -void InterfaceMakerPythonNative::write_prototypes_class_external(ostream &out, Object * obj) -{ - std::string class_name = make_safe_name(obj->_itype.get_scoped_name()); - std::string c_class_name = obj->_itype.get_true_name(); - std::string preferred_name = obj->_itype.get_name(); +void InterfaceMakerPythonNative:: +write_prototypes_class_external(ostream &out, Object *obj) { + std::string class_name = make_safe_name(obj->_itype.get_scoped_name()); + std::string c_class_name = obj->_itype.get_true_name(); + std::string preferred_name = obj->_itype.get_name(); - out << "//********************************************************************\n"; - out << "//*** prototypes for external.. " << class_name << "\n"; - out << "//********************************************************************\n"; - - out << "typedef " << c_class_name << " " << class_name << "_localtype;\n"; - out << "Define_Module_Class_Forward(" << _def->module_name << ", " << class_name << "," << class_name << "_localtype," << classNameFromCppName(preferred_name, false) << ");\n"; + out << "//********************************************************************\n"; + out << "//*** prototypes for external.. " << class_name << "\n"; + out << "//********************************************************************\n"; + out << "typedef " << c_class_name << " " << class_name << "_localtype;\n"; + out << "Define_Module_Class_Forward(" << _def->module_name << ", " << class_name << ", " << class_name << "_localtype, " << classNameFromCppName(preferred_name, false) << ");\n"; } + ///////////////////////////////////////// //////////////////////////////////////////////////// // Function : write_prototypes_class // @@ -755,7 +795,7 @@ write_functions(ostream &out) { Functions::iterator fi; for (fi = _functions.begin(); fi != _functions.end(); ++fi) { Function *func = (*fi); - if (!func->_itype.is_global() && isFunctionLegal(func)) { + if (!func->_itype.is_global() && is_function_legal(func)) { write_function_for_top(out, NULL, func, ""); } } @@ -764,9 +804,9 @@ write_functions(ostream &out) { for (oi = _objects.begin(); oi != _objects.end(); ++oi) { Object *object = (*oi).second; if (object->_itype.is_class() || object->_itype.is_struct()) { - if (isCppTypeLegal(object->_itype._cpptype)) { + if (is_cpp_type_legal(object->_itype._cpptype)) { if (isExportThisRun(object->_itype._cpptype)) { - write_class_details(out,object); + write_class_details(out, object); } } } @@ -777,9 +817,9 @@ write_functions(ostream &out) { Object *object = (*oi).second; if (!object->_itype.get_outer_class()) { if (object->_itype.is_class() || object->_itype.is_struct()) { - if (isCppTypeLegal(object->_itype._cpptype)) { + if (is_cpp_type_legal(object->_itype._cpptype)) { if (isExportThisRun(object->_itype._cpptype)) { - write_module_class(out,object); + write_module_class(out, object); } } } @@ -798,7 +838,7 @@ write_class_details(ostream &out, Object *obj) { //std::string cClassName = obj->_itype.get_scoped_name(); std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); - std::string cClassName = obj->_itype.get_true_name(); + std::string cClassName = obj->_itype.get_true_name(); out << "//********************************************************************\n"; out << "//*** Functions for .. " << cClassName << "\n" ; @@ -883,7 +923,7 @@ write_class_details(ostream &out, Object *obj) { std::map details; std::map::iterator di; builder.get_type(TypeManager::unwrap(cpptype), false); - GetValideChildClasses(details, cpptype->as_struct_type()); + get_valid_child_classes(details, cpptype->as_struct_type()); for (di = details.begin(); di != details.end(); di++) { //InterrogateType ptype =idb->get_type(di->first); if (di->second._is_legal_py_class && !isExportThisRun(di->second._structType)) @@ -947,7 +987,7 @@ write_class_declarations(ostream &out, ostream *out_h, Object *obj) { std::string class_name = make_safe_name(obj->_itype.get_scoped_name()); std::string c_class_name = obj->_itype.get_true_name(); std::string preferred_name = itype.get_name(); - std::string class_struct_name = std::string(CLASS_PREFIX) +class_name; + std::string class_struct_name = std::string(CLASS_PREFIX) + class_name; out << "typedef " << c_class_name << " " << class_name << "_localtype;\n"; if (obj->_itype.has_destructor() || @@ -965,6 +1005,7 @@ write_class_declarations(ostream &out, ostream *out_h, Object *obj) { out << "Define_Module_Class_Private(" << _def->module_name << ", " << class_name << ", " << class_name << "_localtype, " << classNameFromCppName(preferred_name, false) << ");\n"; } } + out << "\n"; if (out_h != NULL) { *out_h << "extern \"C\" " << EXPORT_IMPORT_PREFIX << " struct Dtool_PyTypedObject Dtool_" << class_name << ";\n"; @@ -989,7 +1030,7 @@ write_sub_module(ostream &out, Object *obj) { // Function : write_module_support ///////////////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: -write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *moduledefdef) { +write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { out << "//********************************************************************\n"; out << "//*** Module Object Linker ..\n"; out << "//********************************************************************\n"; @@ -1010,17 +1051,17 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *moduled string name1 = classNameFromCppName(object->_itype.get_enum_value_name(xx), false); string name2 = classNameFromCppName(object->_itype.get_enum_value_name(xx), true); int enum_value = object->_itype.get_enum_value(xx); - out << " PyModule_AddIntConstant(module,\"" << name1 << "\"," << enum_value << ");\n"; + out << " PyModule_AddIntConstant(module, \"" << name1 << "\", " << enum_value << ");\n"; if (name1 != name2) { // Also write the mangled name, for historical purposes. - out << " PyModule_AddIntConstant(module,\"" << name2 << "\"," << enum_value << ");\n"; + out << " PyModule_AddIntConstant(module, \"" << name2 << "\", " << enum_value << ");\n"; } } } } } - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); int num_manifests = idb->get_num_global_manifests(); for (int mi = 0; mi < num_manifests; mi++) { ManifestIndex manifest_index = idb->get_global_manifest(mi); @@ -1034,16 +1075,16 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *moduled string name2 = classNameFromCppName(iman.get_name(), true); if (iman.has_int_value()) { int value = iman.get_int_value(); - out << " PyModule_AddIntConstant(module,\"" << name1 << "\"," << value << ");\n"; + out << " PyModule_AddIntConstant(module, \"" << name1 << "\", " << value << ");\n"; if (name1 != name2) { // Also write the mangled name, for historical purposes. - out << " PyModule_AddIntConstant(module,\"" << name2 << "\"," << value << ");\n"; + out << " PyModule_AddIntConstant(module, \"" << name2 << "\", " << value << ");\n"; } } else { string value = iman.get_definition(); - out << " PyModule_AddStringConstant(module,\"" << name1 << "\",\"" << value << "\");\n"; + out << " PyModule_AddStringConstant(module, \"" << name1 << "\", \"" << value << "\");\n"; if (name1 != name2) { - out << " PyModule_AddStringConstant(module,\"" << name2 << "\",\"" << value << "\");\n"; + out << " PyModule_AddStringConstant(module, \"" << name2 << "\", \"" << value << "\");\n"; } } } @@ -1052,9 +1093,9 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *moduled Object *object = (*oi).second; if (!object->_itype.get_outer_class()) { if (object->_itype.is_class() ||object->_itype.is_struct()) { - if (isCppTypeLegal(object->_itype._cpptype)) { + if (is_cpp_type_legal(object->_itype._cpptype)) { if (isExportThisRun(object->_itype._cpptype)) { - write_sub_module(out,object); + write_sub_module(out, object); } } } @@ -1075,7 +1116,7 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *moduled Functions::iterator fi; for (fi = _functions.begin(); fi != _functions.end(); ++fi) { Function *func = (*fi); - if (!func->_itype.is_global() && isFunctionLegal(func)) { + if (!func->_itype.is_global() && is_function_legal(func)) { string name1 = methodNameFromCppName(func, "", false); string name2 = methodNameFromCppName(func, "", true); out << " { \"" << name1 << "\", (PyCFunction) &" @@ -1095,9 +1136,9 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *moduled out << " {NULL, NULL, 0, NULL}\n" << "};\n\n"; - out << "struct LibraryDef " << moduledefdef->library_name << "_moddef = {python_simple_funcs, BuildInstants};\n"; + out << "struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs, BuildInstants};\n"; if (out_h != NULL) { - *out_h << "extern struct LibraryDef " << moduledefdef->library_name << "_moddef;\n"; + *out_h << "extern struct LibraryDef " << def->library_name << "_moddef;\n"; } } @@ -1105,8 +1146,8 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *moduled ///// Function : write_module ///////////////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: -write_module(ostream &out,ostream *out_h, InterrogateModuleDef *moduledefdef) { - InterfaceMakerPython::write_module(out, out_h, moduledefdef); +write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) { + InterfaceMakerPython::write_module(out, out_h, def); Objects::iterator oi; out << "//********************************************************************\n"; @@ -1114,9 +1155,9 @@ write_module(ostream &out,ostream *out_h, InterrogateModuleDef *moduledefdef) { out << "//********************************************************************\n"; out << "#if PY_MAJOR_VERSION >= 3\n" - << "#define INIT_FUNC PyObject *PyInit_" << moduledefdef->module_name << "\n" + << "#define INIT_FUNC PyObject *PyInit_" << def->module_name << "\n" << "#else\n" - << "#define INIT_FUNC void init" << moduledefdef->module_name << "\n" + << "#define INIT_FUNC void init" << def->module_name << "\n" << "#endif\n\n" << "#ifdef _WIN32\n" @@ -1126,12 +1167,12 @@ write_module(ostream &out,ostream *out_h, InterrogateModuleDef *moduledefdef) { << "#endif\n\n" << "INIT_FUNC() {\n" - << "PyObject *PyInit_" << moduledefdef->module_name << "() {\n" - << " LibraryDef *refs[] = {&" << moduledefdef->library_name << "_moddef, NULL};\n" + << "PyObject *PyInit_" << def->module_name << "() {\n" + << " LibraryDef *refs[] = {&" << def->library_name << "_moddef, NULL};\n" << "#if PY_MAJOR_VERSION >= 3\n" << " return\n" << "#endif\n" - << " Dtool_PyModuleInitHelper(refs, \"" << moduledefdef->module_name << "\");\n" + << " Dtool_PyModuleInitHelper(refs, \"" << def->module_name << "\");\n" << "}\n\n"; } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -1143,6 +1184,7 @@ write_module_class(ostream &out, Object *obj) { bool has_local_repr = false; bool has_local_str = false; bool has_local_richcompare = false; + bool has_local_getbuffer = false; { int num_nested = obj->_itype.number_of_nested_types(); @@ -1192,12 +1234,12 @@ write_module_class(ostream &out, Object *obj) { string name1 = methodNameFromCppName(func, export_class_name, false); string name2 = methodNameFromCppName(func, export_class_name, true); - out << " { \"" << name1 << "\",(PyCFunction ) &" - << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *)" << func->_name << "_comment},\n"; + out << " { \"" << name1 << "\", (PyCFunction) &" + << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *) " << func->_name << "_comment},\n"; ++x; if (name1 != name2) { - out << " { \"" << name2 << "\",(PyCFunction ) &" - << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *)" << func->_name << "_comment},\n"; + out << " { \"" << name2 << "\", (PyCFunction) &" + << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *) " << func->_name << "_comment},\n"; ++x; } @@ -1214,33 +1256,33 @@ write_module_class(ostream &out, Object *obj) { if (obj->_protocol_types & Object::PT_make_copy) { if (!got_copy) { - out << " { \"__copy__\", (PyCFunction)©_from_make_copy, METH_NOARGS, NULL},\n"; + out << " { \"__copy__\", (PyCFunction) ©_from_make_copy, METH_NOARGS, NULL},\n"; got_copy = true; } } else if (obj->_protocol_types & Object::PT_copy_constructor) { if (!got_copy) { - out << " { \"__copy__\", (PyCFunction)©_from_copy_constructor, METH_NOARGS, NULL},\n"; + out << " { \"__copy__\", (PyCFunction) ©_from_copy_constructor, METH_NOARGS, NULL},\n"; got_copy = true; } } if (got_copy && !got_deepcopy) { - out << " { \"__deepcopy__\", (PyCFunction)&map_deepcopy_to_copy, METH_VARARGS, NULL},\n"; + out << " { \"__deepcopy__\", (PyCFunction) &map_deepcopy_to_copy, METH_VARARGS, NULL},\n"; } MakeSeqs::iterator msi; for (msi = obj->_make_seqs.begin(); msi != obj->_make_seqs.end(); ++msi) { string flags = "METH_NOARGS"; if (obj->is_static_method((*msi)->_element_name)) { - flags += "|METH_CLASS"; + flags += " | METH_CLASS"; } string name1 = methodNameFromCppName((*msi)->_seq_name, export_class_name, false); string name2 = methodNameFromCppName((*msi)->_seq_name, export_class_name, true); out << " { \"" << name1 - << "\",(PyCFunction) &" << (*msi)->_name << ", " << flags << ", NULL},\n"; + << "\", (PyCFunction) &" << (*msi)->_name << ", " << flags << ", NULL},\n"; if (name1 != name2) { out << " { \"" << name2 - << "\",(PyCFunction) &" << (*msi)->_name << ", " << flags << ", NULL},\n"; + << "\", (PyCFunction) &" << (*msi)->_name << ", " << flags << ", NULL},\n"; } } @@ -1253,7 +1295,7 @@ write_module_class(ostream &out, Object *obj) { TypeIndex d_type_Index = obj->_itype.get_derivation(di); if (!interrogate_type_is_unpublished(d_type_Index)) { const InterrogateType &d_itype = idb->get_type(d_type_Index); - if (isCppTypeLegal(d_itype._cpptype)) { + if (is_cpp_type_legal(d_itype._cpptype)) { if (!isExportThisRun(d_itype._cpptype)) { _external_imports.insert(make_safe_name(d_itype.get_scoped_name().c_str())); @@ -1268,7 +1310,7 @@ write_module_class(ostream &out, Object *obj) { TypeIndex d_type_Index = obj->_itype.get_derivation(di); if (!interrogate_type_is_unpublished(d_type_Index)) { const InterrogateType &d_itype = idb->get_type(d_type_Index); - if (isCppTypeLegal(d_itype._cpptype)) { + if (is_cpp_type_legal(d_itype._cpptype)) { bases.push_back(make_safe_name(d_itype.get_scoped_name().c_str())); } } @@ -1481,6 +1523,161 @@ write_module_class(ostream &out, Object *obj) { } break; + case WT_getbuffer: + // int __getbuffer__(PyObject *self, Py_buffer *buffer, int flags) + // We map this directly, and assume that the arguments match. The whole point + // of this is to be fast, and we don't want to negate that by first wrapping + // and then unwrapping the arguments again. We also want to guarantee const + // correctness, since that will determine whether a read-only buffer is given. + { + has_local_getbuffer = true; + + Function *func = rfi->first; + out << "//////////////////\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "//////////////////\n"; + out << "static int " << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, Py_buffer *buffer, int flags) {\n"; + out << " " << cClassName << " *local_this = NULL;\n"; + out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **) &local_this);\n"; + out << " if (local_this == NULL) {\n"; + out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n"; + out << " return -1;\n"; + out << " }\n\n"; + + vector_string params_const(1); + vector_string params_nonconst(1); + FunctionRemap *remap_const = NULL; + FunctionRemap *remap_nonconst = NULL; + + // Iterate through the remaps to find the one that matches our parameters. + Function::Remaps::const_iterator ri; + for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { + FunctionRemap *remap = (*ri); + if (remap->_flags & FunctionRemap::F_getbuffer) { + if (remap->_const_method) { + if ((remap->_flags & FunctionRemap::F_explicit_self) == 0) { + params_const.push_back("self"); + } + remap_const = remap; + } else { + if ((remap->_flags & FunctionRemap::F_explicit_self) == 0) { + params_nonconst.push_back("self"); + } + remap_nonconst = remap; + } + } + } + params_const.push_back("buffer"); + params_const.push_back("flags"); + params_nonconst.push_back("buffer"); + params_nonconst.push_back("flags"); + + // We have to distinguish properly between const and nonconst, because the function + // may depend on it to decide whether to provide a writable buffer or a readonly buffer. + const string const_this = "(const " + cClassName + " *)local_this"; + if (remap_const != NULL && remap_nonconst != NULL) { + out << " if (!((Dtool_PyInstDef *)self)->_is_const) {\n"; + out << " return " << remap_nonconst->call_function(out, 4, false, "local_this", params_nonconst) << ";\n"; + out << " } else {\n"; + out << " return " << remap_const->call_function(out, 4, false, const_this, params_const) << ";\n"; + out << " }\n"; + } else if (remap_nonconst != NULL) { + out << " if (!((Dtool_PyInstDef *)self)->_is_const) {\n"; + out << " return " << remap_nonconst->call_function(out, 4, false, "local_this", params_nonconst) << ";\n"; + out << " } else {\n"; + out << " PyErr_SetString(PyExc_TypeError,\n"; + out << " \"Cannot call " << ClassName << ".__getbuffer__() on a const object.\");\n"; + out << " return -1;\n"; + out << " }\n"; + } else if (remap_const != NULL) { + out << " return " << remap_const->call_function(out, 4, false, const_this, params_const) << ";\n"; + } else { + nout << ClassName << "::__getbuffer__ does not match the required signature.\n"; + out << " return -1;\n"; + } + + out << "}\n\n"; + } + break; + + case WT_releasebuffer: + // void __releasebuffer__(PyObject *self, Py_buffer *buffer) + // Same story as __getbuffer__ above. + { + Function *func = rfi->first; + out << "//////////////////\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "//////////////////\n"; + out << "static void " << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, Py_buffer *buffer) {\n"; + out << " " << cClassName << " *local_this = NULL;\n"; + out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **) &local_this);\n"; + out << " if (local_this == NULL) {\n"; + out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n"; + out << " return;\n"; + out << " }\n\n"; + + vector_string params_const(1); + vector_string params_nonconst(1); + FunctionRemap *remap_const = NULL; + FunctionRemap *remap_nonconst = NULL; + + // Iterate through the remaps to find the one that matches our parameters. + Function::Remaps::const_iterator ri; + for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { + FunctionRemap *remap = (*ri); + if (remap->_flags & FunctionRemap::F_releasebuffer) { + if (remap->_const_method) { + if ((remap->_flags & FunctionRemap::F_explicit_self) == 0) { + params_const.push_back("self"); + } + remap_const = remap; + } else { + if ((remap->_flags & FunctionRemap::F_explicit_self) == 0) { + params_nonconst.push_back("self"); + } + remap_nonconst = remap; + } + } + } + params_const.push_back("buffer"); + params_nonconst.push_back("buffer"); + + string return_expr; + const string const_this = "(const " + cClassName + " *)local_this"; + if (remap_const != NULL && remap_nonconst != NULL) { + out << " if (!((Dtool_PyInstDef *)self)->_is_const) {\n"; + return_expr = remap_nonconst->call_function(out, 4, false, "local_this", params_nonconst); + if (!return_expr.empty()) { + out << " " << return_expr << ";\n"; + } + out << " } else {\n"; + return_expr = remap_const->call_function(out, 4, false, const_this, params_const); + if (!return_expr.empty()) { + out << " " << return_expr << ";\n"; + } + out << " }\n"; + } else if (remap_nonconst != NULL) { + // Doesn't matter if there's no const version. We *have* to call it or else we could leak memory. + return_expr = remap_nonconst->call_function(out, 2, false, "local_this", params_nonconst); + if (!return_expr.empty()) { + out << " " << return_expr << ";\n"; + } + } else if (remap_const != NULL) { + return_expr = remap_const->call_function(out, 2, false, const_this, params_const); + if (!return_expr.empty()) { + out << " " << return_expr << ";\n"; + } + } else { + nout << ClassName << "::__releasebuffer__ does not match the required signature.\n"; + out << " return;\n"; + } + + out << "}\n\n"; + } + break; + case WT_none: break; } @@ -1529,14 +1726,14 @@ write_module_class(ostream &out, Object *obj) { out << "//////////////////\n"; out << "static PyObject *Dtool_Repr_" << ClassName << "(PyObject *self) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; - out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; + out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **) &local_this);\n"; out << " if (local_this == NULL) {\n"; out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n"; out << " return NULL;\n"; out << " }\n"; out << " ostringstream os;\n"; if (need_repr == 3) { - out << " _ext_" << ClassName << "_python_repr(local_this, os, \"" + out << " invoke_extension(local_this).python_repr(os, \"" << classNameFromCppName(ClassName, false) << "\");\n"; } else if (need_repr == 2) { out << " local_this->output(os);\n"; @@ -1615,7 +1812,7 @@ write_module_class(ostream &out, Object *obj) { Function::Remaps::const_iterator ri; for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { FunctionRemap *remap = (*ri); - if (isRemapLegal(*remap) && remap->_has_this && remap->_parameters.size() == 2) { + if (is_remap_legal(*remap) && remap->_has_this && remap->_parameters.size() == 2) { remaps.insert(remap); } } @@ -1676,6 +1873,14 @@ write_module_class(ostream &out, Object *obj) { << "#endif\n"; } + // Add flags. + if (obj->_protocol_types & Object::PT_iter) { + out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_flags |= Py_TPFLAGS_HAVE_ITER;\n"; + } + if (has_local_getbuffer) { + out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;\n"; + } + // add bases/// if (bases.size() > 0) { out << " // Dependent objects\n"; @@ -1733,16 +1938,16 @@ write_module_class(ostream &out, Object *obj) { if (has_local_repr) { out << " // __repr__\n"; - out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_repr = &Dtool_Repr_" <_itype.number_of_nested_types(); @@ -1904,6 +2109,7 @@ write_prototype_for(ostream &out, InterfaceMaker::Function *func) { std::string fname = "PyObject *" + func->_name + "(PyObject *self, PyObject *args)"; write_prototype_for_name(out, func, fname); } + //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// @@ -1959,7 +2165,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak out1 << "/******************************************************************\n" << " * Python type method wrapper for\n"; for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { FunctionRemap *remap = (*ri); - if (isRemapLegal(*remap)) { + if (is_remap_legal(*remap)) { int parameter_size = remap->_parameters.size(); if (remap->_has_this && remap->_type != FunctionRemap::T_constructor) parameter_size --; @@ -2136,73 +2342,70 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak // // Support Function used to Sort the name based overrides.. For know must be complex to simple //////////////////////////////////////////////////////// -int GetParnetDepth(CPPType *type) -{ - int answer = 0; -// printf(" %s\n",type->get_local_name().c_str()); +int GetParnetDepth(CPPType *type) { + int answer = 0; +// printf(" %s\n",type->get_local_name().c_str()); - if (TypeManager::is_basic_string_char(type)) { - } else if (TypeManager::is_basic_string_wchar(type)) { - } else if (TypeManager::is_bool(type)) { - } else if (TypeManager::is_unsigned_longlong(type)) { - } else if (TypeManager::is_longlong(type)) { - } else if (TypeManager::is_integer(type)) { - } else if (TypeManager::is_float(type)) { - } else if (TypeManager::is_char_pointer(type)) { - } else if (TypeManager::is_wchar_pointer(type)) { - } else if (TypeManager::is_pointer_to_PyObject(type)) { - } else if (TypeManager::is_pointer(type) ||TypeManager::is_reference(type) || TypeManager::is_struct(type) ) - { - answer ++; - int deepest = 0; - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)),false); - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); + if (TypeManager::is_basic_string_char(type)) { + } else if (TypeManager::is_basic_string_wchar(type)) { + } else if (TypeManager::is_bool(type)) { + } else if (TypeManager::is_unsigned_longlong(type)) { + } else if (TypeManager::is_longlong(type)) { + } else if (TypeManager::is_integer(type)) { + } else if (TypeManager::is_float(type)) { + } else if (TypeManager::is_char_pointer(type)) { + } else if (TypeManager::is_wchar_pointer(type)) { + } else if (TypeManager::is_pointer_to_PyObject(type)) { + } else if (TypeManager::is_pointer_to_Py_buffer(type)) { + } else if (TypeManager::is_pointer(type) || TypeManager::is_reference(type) || TypeManager::is_struct(type)) { + ++answer; + int deepest = 0; + TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)), false); + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + const InterrogateType &itype = idb->get_type(type_index); - if (itype.is_class() ||itype.is_struct()) - { - - int num_derivations = itype.number_of_derivations(); - for (int di = 0; di < num_derivations; di++) - { - TypeIndex d_type_Index = itype.get_derivation(di); - const InterrogateType &d_itype = idb->get_type(d_type_Index); - int this_one = GetParnetDepth(d_itype._cpptype); - if (this_one > deepest) - deepest = this_one; - } + if (itype.is_class() || itype.is_struct()) { + int num_derivations = itype.number_of_derivations(); + for (int di = 0; di < num_derivations; di++) { + TypeIndex d_type_Index = itype.get_derivation(di); + const InterrogateType &d_itype = idb->get_type(d_type_Index); + int this_one = GetParnetDepth(d_itype._cpptype); + if (this_one > deepest) { + deepest = this_one; } - answer += deepest; -// printf(" Class Name %s %d\n",itype.get_name().c_str(),answer); + } } - - + answer += deepest; // printf(" Class Name %s %d\n",itype.get_name().c_str(),answer); - return answer; + } + +// printf(" Class Name %s %d\n",itype.get_name().c_str(),answer); + return answer; } + //////////////////////////////////////////////////////// // The Core sort function for remap calling orders.. ////////////////////////////////////////////////////////// -int RemapCompareLess(FunctionRemap * in1 , FunctionRemap * in2) -{ - if (in1->_parameters.size() != in2->_parameters.size()) - return (in1->_parameters.size() > in2->_parameters.size()); - - int pcount = in1->_parameters.size(); - for (int x = 0; x< pcount; x++) - { - CPPType *orig_type1 = in1->_parameters[x]._remap->get_orig_type(); - CPPType *orig_type2 = in2->_parameters[x]._remap->get_orig_type(); +int RemapCompareLess(FunctionRemap *in1, FunctionRemap *in2) { + if (in1->_parameters.size() != in2->_parameters.size()) { + return (in1->_parameters.size() > in2->_parameters.size()); + } - int pd1 = GetParnetDepth(orig_type1); - int pd2 = GetParnetDepth(orig_type2); - if (pd1 != pd2) - return pd1> pd2; + int pcount = in1->_parameters.size(); + for (int x = 0; x< pcount; x++) { + CPPType *orig_type1 = in1->_parameters[x]._remap->get_orig_type(); + CPPType *orig_type2 = in2->_parameters[x]._remap->get_orig_type(); + + int pd1 = GetParnetDepth(orig_type1); + int pd2 = GetParnetDepth(orig_type2); + if (pd1 != pd2) { + return pd1 > pd2; } + } - // ok maybe something to do with return strength.. + // ok maybe something to do with return strength.. - return false; + return false; } ////////////////////////////////////////////////////////// @@ -2240,7 +2443,7 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, std::set::const_iterator sii; for (sii = remapsin.begin(); sii != remapsin.end() && !coercion_possible; ++sii) { FunctionRemap *remap = (*sii); - if (isRemapLegal(*remap)) { + if (is_remap_legal(*remap)) { int pn = 0; if (remap->_has_this) { // Skip the "this" parameter. It's never coercible. @@ -2252,6 +2455,7 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, if (TypeManager::is_char_pointer(type)) { } else if (TypeManager::is_wchar_pointer(type)) { } else if (TypeManager::is_pointer_to_PyObject(type)) { + } else if (TypeManager::is_pointer_to_Py_buffer(type)) { } else if (TypeManager::is_pointer(type)) { // This is a pointer to an object, so we // might be able to coerce a parameter to it. @@ -2290,7 +2494,7 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, std::vector::iterator sii; for (sii = remaps.begin(); sii != remaps.end(); sii ++) { FunctionRemap *remap = (*sii); - if (isRemapLegal(*remap)) { + if (is_remap_legal(*remap)) { if (remap->_has_this && !remap->_const_method) { // If it's a non-const method, we only allow a // non-const this. @@ -2316,7 +2520,7 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, std::set::iterator sii; for (sii = remapsin.begin(); sii != remapsin.end(); sii ++) { FunctionRemap *remap = (*sii); - if (isRemapLegal(*remap)) { + if (is_remap_legal(*remap)) { if (remap->_has_this && !remap->_const_method) { // If it's a non-const method, we only allow a // non-const this. @@ -2559,7 +2763,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, param_name + "_len)"; } expected_params += "string"; - + } else if (TypeManager::is_bool(type)) { indent(out, indent_level) << "PyObject *" << param_name << ";\n"; format_specifiers += "O"; @@ -2572,10 +2776,10 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, indent(out, indent_level) << "PyObject *" << param_name << ";\n"; format_specifiers += "O"; parameter_list += ", &" + param_name; - extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; + extra_convert += "PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; extra_param_check += " || (" + param_name + "_long == NULL)"; pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)"; - extra_cleanup += " Py_XDECREF(" + param_name + "_long);"; + extra_cleanup += "Py_XDECREF(" + param_name + "_long);"; expected_params += "unsigned long long"; pname_for_pyobject += param_name; @@ -2583,10 +2787,10 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, indent(out, indent_level) << "PyObject *" << param_name << ";\n"; format_specifiers += "O"; parameter_list += ", &" + param_name; - extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; + extra_convert += "PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; extra_param_check += " || (" + param_name + "_long == NULL)"; pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)"; - extra_cleanup += " Py_XDECREF(" + param_name + "_long);"; + extra_cleanup += "Py_XDECREF(" + param_name + "_long);"; expected_params += "long long"; pname_for_pyobject += param_name; @@ -2594,10 +2798,10 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, indent(out, indent_level) << "PyObject *" << param_name << ";\n"; format_specifiers += "O"; parameter_list += ", &" + param_name; - extra_convert += " PyObject *" + param_name + "_uint = PyNumber_Long(" + param_name + ");"; + extra_convert += "PyObject *" + param_name + "_uint = PyNumber_Long(" + param_name + ");"; extra_param_check += " || (" + param_name + "_uint == NULL)"; pexpr_string = "PyLong_AsUnsignedLong(" + param_name + "_uint)"; - extra_cleanup += " Py_XDECREF(" + param_name + "_uint);"; + extra_cleanup += "Py_XDECREF(" + param_name + "_uint);"; expected_params += "unsigned int"; pname_for_pyobject += param_name; @@ -2627,6 +2831,17 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, pname_for_pyobject += param_name; expected_params += "any"; + } else if (TypeManager::is_pointer_to_Py_buffer(type)) { + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + extra_convert += "PyObject *" + param_name + "_buffer = PyMemoryView_FromObject(" + param_name + ");"; + extra_param_check += " || (" + param_name + "_buffer == NULL)"; + pexpr_string = "PyMemoryView_GET_BUFFER(" + param_name + "_buffer)"; + extra_cleanup += "Py_XDECREF(" + param_name + "_buffer);"; + expected_params += "memoryview"; + pname_for_pyobject += param_name; + } else if (TypeManager::is_pointer(type)) { CPPType *obj_type = TypeManager::unwrap(TypeManager::resolve_type(type)); bool const_ok = !TypeManager::is_non_const_pointer_or_ref(orig_type); @@ -2831,12 +3046,12 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, out << "#endif // HAVE_THREADS && !SIMPLE_THREADS\n"; } if (!extra_cleanup.empty()) { - indent(out, extra_indent_level) << extra_cleanup << "\n"; + indent(out, extra_indent_level) << extra_cleanup << "\n"; } return_expr = manage_return_value(out, 4, remap, "return_value"); do_assert_init(out, extra_indent_level, is_constructor, args_cleanup); - pack_return_value(out, extra_indent_level, remap, return_expr, ForwardDeclrs, is_inplace); + pack_return_value(out, extra_indent_level, remap, return_expr, is_inplace); } else { if (remap->_blocking) { @@ -2900,7 +3115,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, << "Py_XDECREF(coerced);\n"; } do_assert_init(out, extra_indent_level, is_constructor, args_cleanup); - pack_return_value(out, extra_indent_level, remap, remap->_return_type->temporary_to_return(return_expr), ForwardDeclrs, is_inplace); + pack_return_value(out, extra_indent_level, remap, remap->_return_type->temporary_to_return(return_expr), is_inplace); } } @@ -2924,138 +3139,194 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, // of the return_type type, as a Python return value. //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: -pack_return_value(ostream &out, int indent_level, - FunctionRemap *remap, string return_expr, ostream &ForwardDeclrs, bool is_inplace) { - CPPType *orig_type = remap->_return_type->get_orig_type(); - CPPType *type = remap->_return_type->get_new_type(); +pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, + const string &return_expr, bool is_inplace) { - if (remap->_return_type->new_type_is_atomic_string()) { + if (remap->_type == FunctionRemap::T_constructor) { + // should only reach this in the INIT function a a Class .. IE the PY exists before the CPP object + // this is were we type to returned a class/struct.. ie CPP Type + CPPType *orig_type = remap->_return_type->get_orig_type(); + + TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)), false); + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + const InterrogateType &itype = idb->get_type(type_index); + indent(out, indent_level) + << "return DTool_PyInit_Finalize(self, " << return_expr << ", &" << CLASS_PREFIX << make_safe_name(itype.get_scoped_name()) << ", true, false);\n"; + + } else { + ParameterRemap *return_type = remap->_return_type; + pack_python_value(out, indent_level, remap, return_type, return_expr, "", is_inplace); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: InterfaceMakerPythonNative::pack_python_value +// Access: Private +// Description: Outputs a command to pack the indicated expression, +// of the return_type type, as a Python value. +// If assign_to is empty, the Python object is +// returned. Otherwise, it is assigned to a variable +// of that name (expected to already be declared). +//////////////////////////////////////////////////////////////////// +void InterfaceMakerPythonNative:: +pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, + ParameterRemap *return_type, const string &return_expr, const string &assign_to, bool is_inplace) { + CPPType *orig_type = return_type->get_orig_type(); + CPPType *type = return_type->get_new_type(); + + string assign_stmt("return "); + if (!assign_to.empty()) { + assign_stmt = assign_to + " = "; + } + + if (return_type->new_type_is_atomic_string()) { if (TypeManager::is_char_pointer(orig_type)) { indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "}\n"; + indent(out, indent_level+2) << assign_stmt << "Py_None;\n"; + indent(out, indent_level) << "} else {\n"; out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromString(" << return_expr << ");\n"; + indent(out, indent_level+2) << assign_stmt + << "PyUnicode_FromString(" << return_expr << ");\n"; out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromString(" << return_expr << ");\n"; + indent(out, indent_level+2) << assign_stmt + << "PyString_FromString(" << return_expr << ");\n"; out << "#endif\n"; + indent(out, indent_level) << "}\n"; + } else if (TypeManager::is_wchar_pointer(orig_type)) { indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "}\n"; - indent(out, indent_level) - << "return PyUnicode_FromWideChar(" + indent(out, indent_level+2) << assign_stmt << "Py_None;\n"; + indent(out, indent_level) << "} else {\n"; + indent(out, indent_level+2) + << assign_stmt << "PyUnicode_FromWideChar(" << return_expr << ", wcslen(" << return_expr << "));\n"; + indent(out, indent_level) << "}\n"; } else if (TypeManager::is_wstring(orig_type)) { - indent(out, indent_level) - << "return PyUnicode_FromWideChar(" - << return_expr << ".data(), (int)" << return_expr << ".length());\n"; + indent(out, indent_level) << assign_stmt + << "PyUnicode_FromWideChar(" + << return_expr << ".data(), (int) " << return_expr << ".length());\n"; } else if (TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) { indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "}\n"; + indent(out, indent_level+2) << assign_stmt << "Py_None;\n"; + indent(out, indent_level) << "} else {\n"; - indent(out, indent_level) - << "return PyUnicode_FromWideChar(" - << return_expr << "->data(), (int)" << return_expr << "->length());\n"; + indent(out, indent_level+2) << assign_stmt + << "PyUnicode_FromWideChar(" + << return_expr << "->data(), (int) " << return_expr << "->length());\n"; + + indent(out, indent_level) << "}\n"; } else if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) { indent(out, indent_level) << "if (" << return_expr<< " == NULL) {\n"; indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "}\n"; + indent(out, indent_level+2) << assign_stmt << "Py_None;\n"; + indent(out, indent_level) << "} else {\n"; out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromStringAndSize(" + indent(out, indent_level+2) << assign_stmt + << "PyUnicode_FromStringAndSize(" << return_expr << "->data(), (Py_ssize_t)" << return_expr << "->length());\n"; out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromStringAndSize(" + indent(out, indent_level+2) << assign_stmt + << "PyString_FromStringAndSize(" << return_expr << "->data(), (Py_ssize_t)" << return_expr << "->length());\n"; out << "#endif\n"; + indent(out, indent_level) << "}\n"; + } else { out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromStringAndSize(" + indent(out, indent_level) << assign_stmt + << "PyUnicode_FromStringAndSize(" << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n"; out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromStringAndSize(" + indent(out, indent_level) << assign_stmt + << "PyString_FromStringAndSize(" << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n"; out << "#endif\n"; } } else if (TypeManager::is_bool(type)) { - indent(out, indent_level) - << "return PyBool_FromLong(" << return_expr << ");\n"; + indent(out, indent_level) << assign_stmt + << "PyBool_FromLong(" << return_expr << ");\n"; } else if (TypeManager::is_unsigned_longlong(type)) { - indent(out, indent_level) - << "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n"; + indent(out, indent_level) << assign_stmt + << "PyLong_FromUnsignedLongLong(" << return_expr << ");\n"; } else if (TypeManager::is_longlong(type)) { - indent(out, indent_level) - << "return PyLong_FromLongLong(" << return_expr << ");\n"; + indent(out, indent_level) << assign_stmt + << "PyLong_FromLongLong(" << return_expr << ");\n"; } else if (TypeManager::is_unsigned_integer(type)){ out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyLong_FromUnsignedLong(" << return_expr << ");\n"; + indent(out, indent_level) << assign_stmt + << "PyLong_FromUnsignedLong(" << return_expr << ");\n"; out << "#else\n"; - indent(out, indent_level) - << "return PyLongOrInt_FromUnsignedLong(" << return_expr << ");\n"; + indent(out, indent_level) << assign_stmt + << "PyLongOrInt_FromUnsignedLong(" << return_expr << ");\n"; out << "#endif\n"; } else if (TypeManager::is_integer(type)) { out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyLong_FromLong(" << return_expr << ");\n"; + indent(out, indent_level) << assign_stmt + << "PyLong_FromLong(" << return_expr << ");\n"; out << "#else\n"; - indent(out, indent_level) - << "return PyInt_FromLong(" << return_expr << ");\n"; + indent(out, indent_level) << assign_stmt + << "PyInt_FromLong(" << return_expr << ");\n"; out << "#endif\n"; } else if (TypeManager::is_float(type)) { - indent(out, indent_level) - << "return PyFloat_FromDouble(" << return_expr << ");\n"; + indent(out, indent_level) << assign_stmt + << "PyFloat_FromDouble(" << return_expr << ");\n"; } else if (TypeManager::is_char_pointer(type)) { indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; + indent(out, indent_level+2) << assign_stmt << "Py_None;\n"; + indent(out, indent_level) << "} else {\n"; + + out << "#if PY_MAJOR_VERSION >= 3\n"; + indent(out, indent_level+2) << assign_stmt + << "PyUnicode_FromString(" << return_expr << ");\n"; + out << "#else\n"; + indent(out, indent_level+2) << assign_stmt + << "PyString_FromString(" << return_expr << ");\n"; + out << "#endif\n"; + indent(out, indent_level) << "}\n"; - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromString(" << return_expr << ");\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromString(" << return_expr << ");\n"; - out << "#endif\n"; } else if (TypeManager::is_wchar_pointer(type)) { indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "}\n"; - indent(out, indent_level) - << "return PyUnicode_FromWideChar(" + indent(out, indent_level+2) << assign_stmt << "Py_None;\n"; + indent(out, indent_level) << "} else {\n"; + indent(out, indent_level+2) << assign_stmt + << "PyUnicode_FromWideChar(" << return_expr << ", wcslen(" << return_expr << "));\n"; + indent(out, indent_level) << "}\n"; + } else if (TypeManager::is_pointer_to_PyObject(type)) { indent(out, indent_level) - << "return " << return_expr << ";\n"; - + << assign_stmt << return_expr << ";\n"; + + } else if (TypeManager::is_pointer_to_Py_buffer(type)) { + indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; + indent(out, indent_level) << " Py_INCREF(Py_None);\n"; + indent(out, indent_level+2) << assign_stmt << "Py_None;\n"; + indent(out, indent_level) << "} else {\n"; + indent(out, indent_level+2) << assign_stmt + << "PyMemoryView_FromBuffer(" << return_expr << ");\n"; + indent(out, indent_level) << "}\n"; + } else if (TypeManager::is_pointer(type)) { string const_flag; if (TypeManager::is_const_pointer_to_anything(type)) { @@ -3082,51 +3353,40 @@ pack_return_value(ostream &out, int indent_level, //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; } - WriteReturnInstance(out, indent_level, return_expr, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); + write_python_instance(out, indent_level, return_expr, assign_to, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); - } else { - if (remap->_type == FunctionRemap::T_constructor) { - // should only reach this in the INIT function a a Class .. IE the PY exists before the CPP object - // this is were we type to returned a class/struct.. ie CPP Type + } else { + std::string owns_memory_flag("true"); + if (remap->_return_value_needs_management) { + owns_memory_flag = "true"; + } else { + owns_memory_flag = "false"; + } - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)), false); + if (remap->_manage_reference_count) { + TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)),false); InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); const InterrogateType &itype = idb->get_type(type_index); - indent(out, indent_level) - << "return DTool_PyInit_Finalize(self, " << return_expr << ", &" <_return_value_needs_management) { - owns_memory_flag = "true"; - } else { - owns_memory_flag = "false"; + TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false); + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); + const InterrogateType &itype = idb->get_type(type_index); + + if (!isExportThisRun(itype._cpptype)) { + _external_imports.insert(make_safe_name(itype.get_scoped_name())); + //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; } - if (remap->_manage_reference_count) { - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)),false); - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); - - if (!isExportThisRun(itype._cpptype)) { - _external_imports.insert(make_safe_name(itype.get_scoped_name())); - //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; - } - - // ForwardDeclrs << "extern \"C\" struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; - WriteReturnInstance(out, indent_level, return_expr, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); - } else { - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false); - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); - - if (!isExportThisRun(itype._cpptype)) { - _external_imports.insert(make_safe_name(itype.get_scoped_name())); - //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; - } - - // ForwardDeclrs << "extern \"C\" struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; - WriteReturnInstance(out, indent_level, return_expr, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); - } + // ForwardDeclrs << "extern \"C\" struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; + write_python_instance(out, indent_level, return_expr, assign_to, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); } } } else if (TypeManager::is_struct(orig_type->as_pointer_type()->_pointing_at)) { @@ -3147,16 +3407,16 @@ pack_return_value(ostream &out, int indent_level, } // ForwardDeclrs << "extern \"C\" struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; - WriteReturnInstance(out, indent_level, return_expr, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); + write_python_instance(out, indent_level, return_expr, assign_to, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); } else { - indent(out, indent_level) << " Should Never Reach This InterfaceMakerPythonNative::pack_return_value"; - //<< "return PyInt_FromLong((int)" << return_expr << ");\n"; + indent(out, indent_level) << " Should Never Reach This InterfaceMakerPythonNative::pack_python_value"; + //<< "return PyInt_FromLong((int) " << return_expr << ");\n"; } } else { // Return None. indent(out, indent_level) - << "return Py_BuildValue(\"\");\n"; + << assign_stmt << "Py_BuildValue(\"\");\n"; } } @@ -3202,7 +3462,7 @@ record_object(TypeIndex type_index) { InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); const InterrogateType &itype = idb->get_type(type_index); - if (!isCppTypeLegal(itype._cpptype)) { + if (!is_cpp_type_legal(itype._cpptype)) { return (Object *)NULL; } @@ -3215,7 +3475,7 @@ record_object(TypeIndex type_index) { int num_constructors = itype.number_of_constructors(); for (int ci = 0; ci < num_constructors; ci++) { function = record_function(itype, itype.get_constructor(ci)); - if (isFunctionLegal(function)) { + if (is_function_legal(function)) { object->_constructors.push_back(function); } } @@ -3224,7 +3484,7 @@ record_object(TypeIndex type_index) { int mi; for (mi = 0; mi < num_methods; mi++) { function = record_function(itype, itype.get_method(mi)); - if (isFunctionLegal(function)) { + if (is_function_legal(function)) { object->_methods.push_back(function); } } @@ -3232,7 +3492,7 @@ record_object(TypeIndex type_index) { int num_casts = itype.number_of_casts(); for (mi = 0; mi < num_casts; mi++) { function = record_function(itype, itype.get_cast(mi)); - if (isFunctionLegal(function)) { + if (is_function_legal(function)) { object->_methods.push_back(function); } } @@ -3245,7 +3505,7 @@ record_object(TypeIndex type_index) { if (!interrogate_type_is_unpublished(d_type_Index)) { if (itype.derivation_has_upcast(di)) { function = record_function(itype, itype.derivation_get_upcast(di)); - if (isFunctionLegal(function)) { + if (is_function_legal(function)) { object->_methods.push_back(function); } } @@ -3256,7 +3516,7 @@ record_object(TypeIndex type_index) { const InterrogateType &base_type = idb->get_type(base_type_index); function = record_function(base_type, itype.derivation_get_downcast(di)); - if (isFunctionLegal(function)) { + if (is_function_legal(function)) { Object * pobject = record_object(base_type_index); if (pobject != NULL) { pobject->_methods.push_back(function); @@ -3354,12 +3614,12 @@ generate_wrappers() { inside_python_native = false; } ////////////////////////////////////////////// -// Function :isCppTypeLegal +// Function :is_cpp_type_legal // // is the cpp object supported by by the dtool_py interface.. ////////////////////////////////////////////// bool InterfaceMakerPythonNative:: -isCppTypeLegal(CPPType *in_ctype) { +is_cpp_type_legal(CPPType *in_ctype) { if (in_ctype == NULL) { return false; } @@ -3385,6 +3645,8 @@ isCppTypeLegal(CPPType *in_ctype) { return true; } else if (TypeManager::is_pointer_to_PyObject(in_ctype)) { return true; + } else if (TypeManager::is_pointer_to_Py_buffer(in_ctype)) { + return true; } //if (answer == false) @@ -3415,7 +3677,7 @@ isExportThisRun(CPPType *ctype) { ///////////////////////////////////////////// bool InterfaceMakerPythonNative:: isExportThisRun(Function *func) { - if (func == NULL || !isFunctionLegal(func)) { + if (func == NULL || !is_function_legal(func)) { return false; } @@ -3429,13 +3691,13 @@ isExportThisRun(Function *func) { } ////////////////////////////////////////////// -// Function : isRemapLegal +// Function : is_remap_legal ////////////////////////////////////////////// bool InterfaceMakerPythonNative:: -isRemapLegal(FunctionRemap &remap) { +is_remap_legal(FunctionRemap &remap) { // return must be legal and managable.. - if (!isCppTypeLegal(remap._return_type->get_orig_type())) { -// printf(" isRemapLegal Return Is Bad %s\n",remap._return_type->get_orig_type()->get_fully_scoped_name().c_str()); + if (!is_cpp_type_legal(remap._return_type->get_orig_type())) { +// printf(" is_remap_legal Return Is Bad %s\n",remap._return_type->get_orig_type()->get_fully_scoped_name().c_str()); return false; } @@ -3447,7 +3709,7 @@ isRemapLegal(FunctionRemap &remap) { // all params must be legal for (int pn = 0; pn < (int)remap._parameters.size(); pn++) { CPPType *orig_type = remap._parameters[pn]._remap->get_orig_type(); - if (!isCppTypeLegal(orig_type)) { + if (!is_cpp_type_legal(orig_type)) { return false; } } @@ -3457,14 +3719,14 @@ isRemapLegal(FunctionRemap &remap) { } //////////////////////////////////////////////////////////////////////// -// Function : isFunctionLegal +// Function : is_function_legal //////////////////////////////////////////////////////////////////////// bool InterfaceMakerPythonNative:: -isFunctionLegal(Function *func) { +is_function_legal(Function *func) { Function::Remaps::const_iterator ri; for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { FunctionRemap *remap = (*ri); - if (isRemapLegal(*remap)) { + if (is_remap_legal(*remap)) { // printf(" Function Is Marked Legal %s\n",func->_name.c_str()); return true; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index 2d9beb0b19..77fcdc16f3 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -34,17 +34,17 @@ public: virtual ~InterfaceMakerPythonNative(); - virtual void write_prototypes(ostream &out,ostream *out_h); - void write_prototypes_class(ostream &out,ostream *out_h, Object * obj) ; - void write_prototypes_class_external(ostream &out, Object * obj); + virtual void write_prototypes(ostream &out, ostream *out_h); + void write_prototypes_class(ostream &out, ostream *out_h, Object *obj) ; + void write_prototypes_class_external(ostream &out, Object *obj); virtual void write_functions(ostream &out); - virtual void write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def); - virtual void write_module_support(ostream &out, ostream *out_h,InterrogateModuleDef *moduledefdef); + virtual void write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def); + virtual void write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def); void write_module_class(ostream &out, Object *cls); - virtual void write_sub_module(ostream &out, Object *obj); + virtual void write_sub_module(ostream &out, Object *obj); virtual bool synthesize_this_parameter(); @@ -74,6 +74,8 @@ private: WT_sequence_size, WT_mapping_setitem, WT_inquiry, + WT_getbuffer, + WT_releasebuffer, }; class SlottedFunctionDef { @@ -102,22 +104,25 @@ private: int indent_level, ostream &forwarddecl, bool inplace, bool coercion_allowed, bool &coercion_attempted, const string &args_cleanup); - - void pack_return_value(ostream &out, int indent_level, - FunctionRemap *remap, std::string return_expr, ostream &forwarddecl, bool in_place); - + + void pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, + const std::string &return_expr, bool in_place); + void pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, + ParameterRemap *return_type, const std::string &return_expr, + const std::string &assign_expr, bool in_place); + void write_make_seq(ostream &out, Object *obj, const std::string &ClassName, MakeSeq *make_seq); - + void write_class_prototypes(ostream &out) ; void write_class_declarations(ostream &out, ostream *out_h, Object *obj); void write_class_details(ostream &out, Object *obj); void do_assert_init(ostream &out, int &indent_level, bool constructor, const string &args_cleanup) const; public: - bool isRemapLegal(FunctionRemap &remap); - bool isFunctionLegal( Function *func); - bool isCppTypeLegal(CPPType *ctype); + bool is_remap_legal(FunctionRemap &remap); + bool is_function_legal( Function *func); + bool is_cpp_type_legal(CPPType *ctype); bool isExportThisRun(CPPType *ctype); bool isExportThisRun(Function *func); bool isFunctionWithThis( Function *func); @@ -131,11 +136,11 @@ public: bool _can_downcast; bool _is_legal_py_class; }; - - void GetValideChildClasses( std::map< std::string ,CastDetails > &answer, CPPStructType * inclass, const std::string &up_cast_seed = "", bool downcastposible = true); - bool DoesInheritFromIsClass( const CPPStructType * inclass, const std::string &name); + + void get_valid_child_classes(std::map &answer, CPPStructType *inclass, const std::string &upcast_seed = "", bool can_downcast = true); + bool DoesInheritFromIsClass(const CPPStructType * inclass, const std::string &name); bool IsPandaTypedObject(CPPStructType * inclass) { return DoesInheritFromIsClass(inclass,"TypedObject"); }; - void WriteReturnInstance(ostream &out, int indent_level, std::string &return_expr, std::string &ows_memory_flag,const std::string &class_name, CPPType *ctype, bool inplace, const std::string &const_flag); + void write_python_instance(ostream &out, int indent_level, const std::string &return_expr, const std::string &assign_expr, std::string &owns_memory_flag, const std::string &class_name, CPPType *ctype, bool inplace, const std::string &const_flag); string HasAGetKeyFunction(const InterrogateType &itype_class); bool HasAGetClassTypeFunction(const InterrogateType &itype_class); int NeedsAStrFunction(const InterrogateType &itype_class); diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx index 51eb0bbb3a..e98ef7fc87 100644 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ b/dtool/src/interrogate/interrogateBuilder.cxx @@ -128,17 +128,16 @@ read_command_file(istream &in) { void InterrogateBuilder:: do_command(const string &command, const string ¶ms) { - if(command == "forcevisible") - { - CPPType *type = parser.parse_type(params); - if (type == (CPPType *)NULL) { - nout << "Unknown type: allowtype " << params << "\n"; - } else { - type = type->resolve_type(&parser, &parser); - type->_vis = min_vis; - } - } - else if (command == "forcetype") { + if (command == "forcevisible") { + CPPType *type = parser.parse_type(params); + if (type == (CPPType *)NULL) { + nout << "Unknown type: allowtype " << params << "\n"; + } else { + type = type->resolve_type(&parser, &parser); + type->_vis = min_vis; + } + + } else if (command == "forcetype") { // forcetype explicitly exports the given type. CPPType *type = parser.parse_type(params); if (type == (CPPType *)NULL) { @@ -364,7 +363,6 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int << "#include \"dconfig.h\"\n"; } - ostringstream declaration_bodies; if (watch_asserts) { @@ -377,7 +375,8 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int if (library_name.size() > 1) { declaration_bodies << "#define PANDA_LIBRARY_NAME_" << library_name << "\n"; } - declaration_bodies << "#include \"py_panda.h\" \n"; + declaration_bodies << "#include \"py_panda.h\"\n"; + declaration_bodies << "#include \"extension.h\"\n"; } declaration_bodies << "\n"; @@ -393,12 +392,6 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int } else { declaration_bodies << "#include <" << filename << ">\n"; } - // Check if it's a special extension file. - } else if (filename.length() > 6 && filename.substr(filename.length() - 6) == "_ext.I") { - declaration_bodies - << "#define this _ext_this\n" - << "#include \"" << filename << "\"\n" - << "#undef this\n"; } } declaration_bodies << "\n"; @@ -1757,6 +1750,11 @@ get_function(CPPInstance *function, string description, ifunction->_flags |= InterrogateFunction::F_operator_typecast; } + if (function->_storage_class & CPPInstance::SC_virtual) { + // This is a virtual function. + ifunction->_flags |= InterrogateFunction::F_virtual; + } + ifunction->_flags |= flags; ifunction->_instances->insert(InterrogateFunction::Instances::value_type(function_signature, function)); ifunction->_expression = expression; diff --git a/dtool/src/interrogate/interrogateBuilder.h b/dtool/src/interrogate/interrogateBuilder.h index 60ae3579bd..06b60f6fea 100644 --- a/dtool/src/interrogate/interrogateBuilder.h +++ b/dtool/src/interrogate/interrogateBuilder.h @@ -56,7 +56,7 @@ public: void read_command_file(istream &in); void do_command(const string &command, const string ¶ms); void build(); - void write_code(ostream &out_code,ostream *out_include, InterrogateModuleDef *def); + void write_code(ostream &out_code, ostream *out_include, InterrogateModuleDef *def); InterrogateModuleDef *make_module_def(int file_identifier); static string clean_identifier(const string &name); diff --git a/dtool/src/interrogate/parameterRemapConstToNonConst.h b/dtool/src/interrogate/parameterRemapConstToNonConst.h index bb06157056..d6f6e4315f 100644 --- a/dtool/src/interrogate/parameterRemapConstToNonConst.h +++ b/dtool/src/interrogate/parameterRemapConstToNonConst.h @@ -23,7 +23,7 @@ // Class : ParameterRemapConstToNonConst // Description : A ParameterRemap class that handles remapping a // simple const parameter (like const int) to an -// ordinary parameter (line int). It doesn't apply to +// ordinary parameter (like int). It doesn't apply to // const references or const pointers, however. //////////////////////////////////////////////////////////////////// class ParameterRemapConstToNonConst : public ParameterRemap { diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index 9188fd7d34..8dc01d9855 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -23,6 +23,7 @@ #include "cppPointerType.h" #include "cppSimpleType.h" #include "cppStructType.h" +#include "cppTemplateScope.h" #include "cppTypeDeclaration.h" #include "pnotify.h" #include "cppTypedef.h" @@ -1052,6 +1053,35 @@ is_const_ref_to_pointer_to_base(CPPType *type) { } } +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::is_pair +// Access: Public, Static +// Description: Returns true if the type is pair<>, or +// a reference to it. +//////////////////////////////////////////////////////////////////// +bool TypeManager:: +is_pair(CPPType *type) { + // We only check the simple name of the type against pair, + // since we need to allow for the various template instantiations of + // this thing. + if (type->get_simple_name() == "pair") { + return true; + } + + switch (type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_pair(type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_reference: + return is_pair(type->as_reference_type()->_pointing_at); + + default: + break; + } + + return false; +} + //////////////////////////////////////////////////////////////////// // Function: TypeManager::is_pointer_to_PyObject // Access: Public, Static @@ -1090,6 +1120,43 @@ is_PyObject(CPPType *type) { } } +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::is_pointer_to_Py_buffer +// Access: Public, Static +// Description: Returns true if the indicated type is Py_buffer *. +//////////////////////////////////////////////////////////////////// +bool TypeManager:: +is_pointer_to_Py_buffer(CPPType *type) { + switch (type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_pointer_to_Py_buffer(type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_pointer: + return is_Py_buffer(type->as_pointer_type()->_pointing_at); + + default: + return false; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::is_Py_buffer +// Access: Public, Static +// Description: Returns true if the indicated type is Py_buffer. +//////////////////////////////////////////////////////////////////// +bool TypeManager:: +is_Py_buffer(CPPType *type) { + switch (type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_Py_buffer(type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_extension: + return (type->get_local_name(&parser) == "Py_buffer"); + + default: + return false; + } +} //////////////////////////////////////////////////////////////////// // Function: TypeManager::is_ostream @@ -1390,6 +1457,40 @@ get_pointer_type(CPPStructType *pt_type) { return (CPPType *)NULL; } +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::get_template_parameter_type +// Access: Public, Static +// Description: Returns the ith template parameter type. For +// instance, if the type is pair, then this +// function will return type A when passing 0 and +// type B when passing 1, and NULL otherwise. +//////////////////////////////////////////////////////////////////// +CPPType *TypeManager:: +get_template_parameter_type(CPPType *source_type, int i) { + switch (source_type->get_subtype()) { + case CPPDeclaration::ST_const: + return get_template_parameter_type(source_type->as_const_type()->_wrapped_around, i); + + case CPPDeclaration::ST_reference: + return get_template_parameter_type(source_type->as_reference_type()->_pointing_at, i); + } + + CPPStructType *type = source_type->as_struct_type(); + if (type == NULL) { + return NULL; + } + + // I'm not sure how reliable this is, but I don't know if there + // is a more proper way to access this. + CPPTemplateParameterList *templ = type->_ident->_names.back().get_templ(); + if (templ == NULL || i >= templ->_parameters.size()) { + return NULL; + } + + CPPDeclaration *decl = templ->_parameters[i]; + return decl->as_type(); +} + //////////////////////////////////////////////////////////////////// // Function: TypeManager::wrap_pointer // Access: Public, Static diff --git a/dtool/src/interrogate/typeManager.h b/dtool/src/interrogate/typeManager.h index 5ec362af84..938fca3c97 100644 --- a/dtool/src/interrogate/typeManager.h +++ b/dtool/src/interrogate/typeManager.h @@ -76,6 +76,7 @@ public: static bool is_const_ref_to_basic_string_wchar(CPPType *type); static bool is_const_ptr_to_basic_string_wchar(CPPType *type); static bool is_wstring(CPPType *type); + static bool is_pair(CPPType *type); static bool is_bool(CPPType *type); static bool is_integer(CPPType *type); static bool is_unsigned_integer(CPPType *type); @@ -90,6 +91,8 @@ public: 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 is_pointer_to_Py_buffer(CPPType *type); + static bool is_Py_buffer(CPPType *type); static bool involves_unpublished(CPPType *type); static bool involves_protected(CPPType *type); @@ -103,6 +106,7 @@ public: static CPPType *unwrap(CPPType *type); static CPPType *get_pointer_type(CPPStructType *pt_type); + static CPPType *get_template_parameter_type(CPPType *type, int i = 0); static CPPType *wrap_pointer(CPPType *type); static CPPType *wrap_const_pointer(CPPType *type); diff --git a/dtool/src/interrogatedb/Sources.pp b/dtool/src/interrogatedb/Sources.pp index 572467bd65..56074a83f9 100644 --- a/dtool/src/interrogatedb/Sources.pp +++ b/dtool/src/interrogatedb/Sources.pp @@ -17,7 +17,7 @@ interrogateType.I interrogateType.h \ interrogate_datafile.I interrogate_datafile.h \ interrogate_interface.h interrogate_request.h \ - py_panda.h \ + extension.h py_panda.h \ vector_int.h #define INCLUDED_SOURCES \ @@ -37,7 +37,7 @@ #define INSTALL_HEADERS \ interrogate_interface.h interrogate_request.h vector_int.h \ config_interrogatedb.h \ - py_panda.h \ + extension.h py_panda.h \ vector_int.h #end lib_target diff --git a/dtool/src/interrogatedb/extension.h b/dtool/src/interrogatedb/extension.h new file mode 100644 index 0000000000..9eeaffbae9 --- /dev/null +++ b/dtool/src/interrogatedb/extension.h @@ -0,0 +1,75 @@ +// Filename: extension.h +// Created by: rdb (11Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef EXTENSION_H +#define EXTENSION_H + +#include "dtoolbase.h" + +struct _object; +typedef struct _object PyObject; + +//////////////////////////////////////////////////////////////////// +// Class : ExtensionBase +// Description : This is where all extensions should derive from. +// It defines the _self and _this members that can +// be used from the extension method. +//////////////////////////////////////////////////////////////////// +template +class EXPCL_DTOOLCONFIG ExtensionBase { +public: + T * _this; + PyObject * _self; +}; + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : The default class template does not define any +// methods. Classes that are extended should create +// a specialization of this class template. +//////////////////////////////////////////////////////////////////// +template +class EXPCL_DTOOLCONFIG Extension : public ExtensionBase { +}; + +//////////////////////////////////////////////////////////////////// +// Function : invoke_extension +// Description : Creates a new extension object for the given +// pointer that can then be used to call extension +// methods, as follows: +// invoke_extension((MyClass) *ptr).method() +//////////////////////////////////////////////////////////////////// +template +inline Extension +invoke_extension(T *ptr, PyObject *self = NULL) { + Extension ext; + ext._this = ptr; + ext._self = self; + return ext; +} + +//////////////////////////////////////////////////////////////////// +// Function : invoke_extension +// Description : The const version of the above function. +//////////////////////////////////////////////////////////////////// +template +inline const Extension +invoke_extension(const T *ptr, PyObject *self = NULL) { + Extension ext; + ext._this = (T *) ptr; + ext._self = self; + return ext; +} + +#endif diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index 48c9d42563..55b4904b8a 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -437,7 +437,7 @@ RegisterRuntimeClass(Dtool_PyTypedObject * otype, int class_id) { Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type) { RunTimeTypeDictionary::iterator di = GetRunTimeDictionary().find(type); if (di != GetRunTimeDictionary().end()) { - return di->second; + return di->second; } else { int type2 = get_best_parent_from_Set(type, GetRunTimeTypeList()); di = GetRunTimeDictionary().find(type2); @@ -468,6 +468,7 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) { newdef[offset].ml_flags = 0; #if PY_MAJOR_VERSION >= 3 + cerr << "About to create module " << modulename << "\n"; struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, modulename, @@ -477,6 +478,7 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) { NULL, NULL, NULL, NULL }; PyObject *module = PyModule_Create(&moduledef); + cerr << "Module created!\n"; #else PyObject *module = Py_InitModule((char *)modulename, newdef); #endif diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index 86b6888bef..6ca20c7586 100755 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -221,7 +221,7 @@ struct Dtool_PyTypedObject { 0, /* tp_str */ \ PyObject_GenericGetAttr, /* tp_getattro */ \ PyObject_GenericSetAttr, /* tp_setattro */ \ - 0, /* tp_as_buffer */ \ + &Dtool_PyBufferProcs_##CLASS_NAME, /* tp_as_buffer */ \ (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES), /* tp_flags */ \ 0, /* tp_doc */ \ 0, /* tp_traverse */ \ @@ -310,6 +310,11 @@ struct Dtool_PyTypedObject { 0,/*binaryfunc mp_subscript */ \ 0,/*objobjargproc mp_ass_subscript */ \ }; \ + static PyMappingMethods Dtool_PyBufferProcs_##CLASS_NAME = \ + { \ + 0,/*getbufferproc bf_getbuffer */ \ + 0,/*releasebufferproc bf_releasebuffer */ \ + }; \ Define_Dtool_PyTypedObject(MODULE_NAME, CLASS_NAME, PUBLIC_NAME) #else // Python 2: @@ -373,6 +378,15 @@ struct Dtool_PyTypedObject { 0,/*binaryfunc mp_subscript */ \ 0,/*objobjargproc mp_ass_subscript */ \ }; \ + static PyBufferProcs Dtool_PyBufferProcs_##CLASS_NAME = \ + { \ + 0,/*readbufferproc bf_getreadbuffer */ \ + 0,/*writebufferproc bf_getwritebuffer */ \ + 0,/*segcountproc bf_getsegcount */ \ + 0,/*charbufferproc bf_getcharbuffer */ \ + 0,/*getbufferproc bf_getbuffer */ \ + 0,/*releasebufferproc bf_releasebuffer */ \ + }; \ Define_Dtool_PyTypedObject(MODULE_NAME, CLASS_NAME, PUBLIC_NAME) #endif diff --git a/dtool/src/parser-inc/OVR.h b/dtool/src/parser-inc/OVR.h index b446d1a235..7d07655724 100644 --- a/dtool/src/parser-inc/OVR.h +++ b/dtool/src/parser-inc/OVR.h @@ -11,5 +11,6 @@ namespace OVR { class SensorInfo; class SensorFusion; + template class DeviceEnumerator; template class Ptr; }; diff --git a/dtool/src/parser-inc/Python.h b/dtool/src/parser-inc/Python.h index ee4afdab0a..f0c9d32511 100755 --- a/dtool/src/parser-inc/Python.h +++ b/dtool/src/parser-inc/Python.h @@ -23,5 +23,6 @@ class PyObject; class PyThreadState; typedef int Py_ssize_t; +struct Py_buffer; #endif // PYTHON_H diff --git a/panda/src/express/Sources.pp b/panda/src/express/Sources.pp index 3b35e210e2..e64467fbba 100644 --- a/panda/src/express/Sources.pp +++ b/panda/src/express/Sources.pp @@ -70,6 +70,7 @@ virtualFileMountSystem.h virtualFileMountSystem.I \ virtualFileSimple.h virtualFileSimple.I \ virtualFileSystem.h virtualFileSystem.I \ + virtualFileSystem_ext.h virtualFileSystem_ext.cxx \ weakPointerCallback.I weakPointerCallback.h \ weakPointerTo.I weakPointerTo.h \ weakPointerToBase.I weakPointerToBase.h \ diff --git a/panda/src/express/pointerToArray.I b/panda/src/express/pointerToArray.I index c9f19c2d18..d072311031 100644 --- a/panda/src/express/pointerToArray.I +++ b/panda/src/express/pointerToArray.I @@ -83,11 +83,12 @@ PointerToArray(const PointerToArray ©) : // Access: Published // Description: This special constructor accepts a Python list of // elements, or a Python string (or a bytes object, -// in Python 3). +// in Python 3), or any object that supports the +// Python buffer protocol. //////////////////////////////////////////////////////////////////// template PointerToArray:: -PointerToArray(PyObject *self, PyObject *sequence) : +PointerToArray(PyObject *self, PyObject *source) : PointerToArrayBase((ReferenceCountedVector *)NULL), _type_handle(get_type_handle(Element)) { @@ -95,9 +96,33 @@ PointerToArray(PyObject *self, PyObject *sequence) : // self in the constructor--the caller can't initialize this for us. ((Dtool_PyInstDef *)self)->_ptr_to_object = this; - if (!PySequence_Check(sequence)) { + if (PyObject_CheckBuffer(source)) { + // User passed a buffer object. + Py_buffer view; + if (PyObject_GetBuffer(source, &view, PyBUF_CONTIG_RO) == -1) { + PyErr_SetString(PyExc_TypeError, "PointerToArray constructor requires a contiguous buffer"); + return; + } + + if (view.itemsize != 1 && view.itemsize != sizeof(Element)) { + PyErr_SetString(PyExc_TypeError, "buffer.itemsize does not match PointerToArray element size"); + return; + } + + int num_elements = view.len / sizeof(Element); + insert(begin(), num_elements, Element()); + + if (view.len > 0) { + memcpy(p(), view.buf, view.len); + } + + PyBuffer_Release(&view); + return; + } + + if (!PySequence_Check(source)) { // If passed with a non-sequence, this isn't the right constructor. - PyErr_SetString(PyExc_TypeError, "PointerToArray constructor requires a sequence"); + PyErr_SetString(PyExc_TypeError, "PointerToArray constructor requires a sequence or buffer object"); return; } @@ -105,8 +130,8 @@ PointerToArray(PyObject *self, PyObject *sequence) : // character-at-a-time, just load the whole string as a data // buffer. #if PY_MAJOR_VERSION >= 3 - if (PyBytes_Check(sequence)) { - int size = PyBytes_Size(sequence); + if (PyBytes_Check(source)) { + int size = PyBytes_Size(source); if (size % sizeof(Element) != 0) { ostringstream stream; stream << "Buffer not a multiple of " << sizeof(Element) << " bytes"; @@ -121,14 +146,14 @@ PointerToArray(PyObject *self, PyObject *sequence) : // Hope there aren't any constructors or destructors involved // here. if (size != 0) { - const char *data = PyBytes_AsString(sequence); + const char *data = PyBytes_AsString(source); memcpy(p(), data, size); } return; } #else - if (PyString_CheckExact(sequence)) { - int size = PyString_Size(sequence); + if (PyString_CheckExact(source)) { + int size = PyString_Size(source); if (size % sizeof(Element) != 0) { ostringstream stream; stream << "Buffer not a multiple of " << sizeof(Element) << " bytes"; @@ -143,7 +168,7 @@ PointerToArray(PyObject *self, PyObject *sequence) : // Hope there aren't any constructors or destructors involved // here. if (size != 0) { - const char *data = PyString_AsString(sequence); + const char *data = PyString_AsString(source); memcpy(p(), data, size); } return; @@ -152,9 +177,9 @@ PointerToArray(PyObject *self, PyObject *sequence) : // Now construct the internal list by copying the elements // one-at-a-time from Python. - int size = PySequence_Size(sequence); + int size = PySequence_Size(source); for (int i = 0; i < size; ++i) { - PyObject *item = PySequence_GetItem(sequence, i); + PyObject *item = PySequence_GetItem(source, i); if (item == NULL) { return; } @@ -715,6 +740,32 @@ get_ref_count() const { return ((this->_void_ptr) == NULL) ? 0 : ((To *)(this->_void_ptr))->get_ref_count(); } +//////////////////////////////////////////////////////////////////// +// Function: PointerToArray::ref +// Access: Public +// Description: Increments the reference count of the underlying vector. +//////////////////////////////////////////////////////////////////// +template +INLINE void PointerToArray:: +ref() const { + if ((this->_void_ptr) == NULL) { + ((PointerToArray *)this)->reassign(new ReferenceCountedVector(_type_handle)); + } + ((To *)(this->_void_ptr))->ref(); +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToArray::unref +// Access: Public +// Description: Decrements the reference count of the underlying vector. +//////////////////////////////////////////////////////////////////// +template +INLINE bool PointerToArray:: +unref() const { + nassertr((this->_void_ptr) != NULL, true); + return ((To *)(this->_void_ptr))->unref(); +} + //////////////////////////////////////////////////////////////////// // Function: PointerToArray::get_node_ref_count // Access: Public @@ -841,8 +892,8 @@ ConstPointerToArray(const ConstPointerToArray ©) : //////////////////////////////////////////////////////////////////// template INLINE ConstPointerToArray:: -ConstPointerToArray(PyObject *self, PyObject *sequence) : - PointerToArrayBase(PointerToArray(self, sequence)), +ConstPointerToArray(PyObject *self, PyObject *source) : + PointerToArrayBase(PointerToArray(self, source)), _type_handle(get_type_handle(Element)) { } @@ -1164,6 +1215,32 @@ get_ref_count() const { return ((this->_void_ptr) == NULL) ? 0 : ((To *)(this->_void_ptr))->get_ref_count(); } +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerToArray::ref +// Access: Public +// Description: Increments the reference count of the underlying vector. +//////////////////////////////////////////////////////////////////// +template +INLINE void ConstPointerToArray:: +ref() const { + if ((this->_void_ptr) == NULL) { + ((ConstPointerToArray *)this)->reassign(new ReferenceCountedVector(_type_handle)); + } + ((To *)(this->_void_ptr))->ref(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerToArray::unref +// Access: Public +// Description: Decrements the reference count of the underlying vector. +//////////////////////////////////////////////////////////////////// +template +INLINE bool ConstPointerToArray:: +unref() const { + nassertr((this->_void_ptr) != NULL, true); + return ((To *)(this->_void_ptr))->unref(); +} + //////////////////////////////////////////////////////////////////// // Function: ConstPointerToArray::get_node_ref_count // Access: Public @@ -1252,4 +1329,151 @@ clear() { ((ConstPointerToArray *)this)->reassign((ReferenceCountedVector *)NULL); } +#ifdef HAVE_PYTHON +//////////////////////////////////////////////////////////////////// +// Function: PointerToArray::__getbuffer__ +// Access: Published +// Description: This is used to implement the buffer protocol, in +// order to allow efficient access to the array data +// through a Python multiview object. +//////////////////////////////////////////////////////////////////// +template +INLINE int PointerToArray:: +__getbuffer__(PyObject *self, Py_buffer *view, int flags) { + + const char *format = get_format_code(Element); + cerr << "non-const __getbuffer__ with fmt " << format << "\n"; + if (format == NULL) { + // Not supported. + return -1; + } + + if (self != NULL) { + Py_INCREF(self); + } + view->obj = self; + view->buf = (void*) p(); + view->len = size() * sizeof(Element); + view->readonly = 0; + view->itemsize = sizeof(Element); + view->format = NULL; + if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { + view->format = (char*) format; + } + view->ndim = 1; + view->shape = NULL; + if ((flags & PyBUF_ND) == PyBUF_ND) { + // This leaks, which sucks, but __releasebuffer__ doesn't give us + // the same pointer, so we would need to store it elsewhere if we + // wanted to delete it there. Eh, it's just an int, who cares. + view->shape = new Py_ssize_t(size()); + } + view->strides = NULL; + if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { + view->strides = &(view->itemsize); + } + view->suboffsets = NULL; + + // Store a reference to ourselves on the Py_buffer object + // as a reminder that we have increased our refcount. + ref(); + view->internal = (void*) this; + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToArray::__releasebuffer__ +// Access: Published +// Description: Releases the buffer allocated by __getbuffer__. +//////////////////////////////////////////////////////////////////// +template +INLINE void PointerToArray:: +__releasebuffer__(PyObject *self, Py_buffer *view) const { + // Note: PyBuffer_Release automatically decrements view->obj. + + if (view->internal != NULL) { + // Oh, right, let's not forget to unref this. + ((const PointerToArray *) view->internal)->unref(); + view->internal = NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerToArray::__getbuffer__ +// Access: Published +// Description: This is used to implement the buffer protocol, in +// order to allow efficient access to the array data +// through a Python multiview object. +//////////////////////////////////////////////////////////////////// +template +INLINE int ConstPointerToArray:: +__getbuffer__(PyObject *self, Py_buffer *view, int flags) const { + + if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) { + cerr << "writable buffer requested of const array\n"; + PyErr_SetString(PyExc_BufferError, + "Object is not writable."); + return -1; + } + + const char *format = get_format_code(Element); + cerr << "const __getbuffer__ with fmt " << format << "\n"; + if (format == NULL) { + // Not supported. + return -1; + } + + if (self != NULL) { + Py_INCREF(self); + } + view->obj = self; + view->buf = (void*) p(); + view->len = size() * sizeof(Element); + view->readonly = 1; + view->itemsize = sizeof(Element); + view->format = NULL; + if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { + view->format = (char*) format; + } + view->ndim = 1; + view->shape = NULL; + if ((flags & PyBUF_ND) == PyBUF_ND) { + // This leaks, which sucks, but __releasebuffer__ doesn't give us + // the same pointer, so we would need to store it elsewhere if we + // wanted to delete it there. Eh, it's just an int, who cares. + view->shape = new Py_ssize_t(size()); + } + view->strides = NULL; + if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { + view->strides = &(view->itemsize); + } + view->suboffsets = NULL; + + // Store a reference to ourselves on the Py_buffer object + // as a reminder that we have increased our refcount. + ref(); + view->internal = (void*) this; + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerToArray::__releasebuffer__ +// Access: Published +// Description: Releases the buffer allocated by __getbuffer__. +//////////////////////////////////////////////////////////////////// +template +INLINE void ConstPointerToArray:: +__releasebuffer__(PyObject *self, Py_buffer *view) const { + // Note: PyBuffer_Release automatically decrements obj->view. + + if (view->internal != NULL) { + // Oh, right, let's not forget to unref this. + ((const PointerToArray *) view->internal)->unref(); + view->internal = NULL; + } +} +#endif // HAVE_PYTHON + #endif // CPPPARSER diff --git a/panda/src/express/pointerToArray.h b/panda/src/express/pointerToArray.h index fb7c89e77d..1472f9d975 100644 --- a/panda/src/express/pointerToArray.h +++ b/panda/src/express/pointerToArray.h @@ -113,7 +113,7 @@ PUBLISHED: INLINE PointerToArray(const PointerToArray ©); #ifdef HAVE_PYTHON - PointerToArray(PyObject *self, PyObject *sequence); + PointerToArray(PyObject *self, PyObject *source); #endif INLINE size_type size() const; @@ -130,6 +130,11 @@ PUBLISHED: INLINE int get_ref_count() const; INLINE int get_node_ref_count() const; +#ifdef HAVE_PYTHON + int __getbuffer__(PyObject *self, Py_buffer *view, int flags); + void __releasebuffer__(PyObject *self, Py_buffer *view) const; +#endif + #else // CPPPARSER // This is the actual, complete interface. typedef TYPENAME PointerToArrayBase::To To; @@ -150,7 +155,7 @@ public: INLINE PointerToArray(const PointerToArray ©); #ifdef HAVE_PYTHON - PointerToArray(PyObject *self, PyObject *sequence); + PointerToArray(PyObject *self, PyObject *source); #endif public: @@ -223,11 +228,18 @@ public: INLINE void set_void_ptr(void* p); INLINE int get_ref_count() const; + INLINE void ref() const; + INLINE bool unref() const; INLINE int get_node_ref_count() const; INLINE void node_ref() const; INLINE bool node_unref() const; +#ifdef HAVE_PYTHON + int __getbuffer__(PyObject *self, Py_buffer *view, int flags); + void __releasebuffer__(PyObject *self, Py_buffer *view) const; +#endif + // Reassignment is by pointer, not memberwise as with a vector. INLINE PointerToArray & operator = (ReferenceCountedVector *ptr); @@ -268,7 +280,7 @@ PUBLISHED: INLINE ConstPointerToArray(const ConstPointerToArray ©); #ifdef HAVE_PYTHON - INLINE ConstPointerToArray(PyObject *self, PyObject *sequence); + INLINE ConstPointerToArray(PyObject *self, PyObject *source); #endif typedef TYPENAME pvector::size_type size_type; @@ -280,6 +292,11 @@ PUBLISHED: INLINE int get_ref_count() const; INLINE int get_node_ref_count() const; +#ifdef HAVE_PYTHON + int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const; + void __releasebuffer__(PyObject *self, Py_buffer *view) const; +#endif + #else // CPPPARSER // This is the actual, complete interface. typedef TYPENAME PointerToArrayBase::To To; @@ -303,7 +320,7 @@ PUBLISHED: INLINE ConstPointerToArray(const ConstPointerToArray ©); #ifdef HAVE_PYTHON - INLINE ConstPointerToArray(PyObject *self, PyObject *sequence); + INLINE ConstPointerToArray(PyObject *self, PyObject *source); #endif // Duplicating the interface of vector. @@ -343,11 +360,18 @@ PUBLISHED: INLINE string get_subdata(size_type n, size_type count) const; INLINE int get_ref_count() const; + INLINE void ref() const; + INLINE bool unref() const; INLINE int get_node_ref_count() const; INLINE void node_ref() const; INLINE bool node_unref() const; +#ifdef HAVE_PYTHON + int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const; + void __releasebuffer__(PyObject *self, Py_buffer *view) const; +#endif + // Reassignment is by pointer, not memberwise as with a vector. INLINE ConstPointerToArray & operator = (ReferenceCountedVector *ptr); @@ -372,12 +396,40 @@ private: friend class PointerToArray; }; - // And the brevity macros. - #define PTA(type) PointerToArray< type > #define CPTA(type) ConstPointerToArray< type > +#ifdef HAVE_PYTHON +// This macro is used to map a data type to a format code +// as used in the Python 'struct' and 'array' modules. +#define get_format_code(type) _get_format_code((const type *)0) +#define define_format_code(code, type) template<> \ + INLINE const char *_get_format_code(const type *) { \ + return code; \ + } + +template +INLINE const char *_get_format_code(const T *) { + return NULL; +} + +define_format_code("c", char); +define_format_code("b", signed char); +define_format_code("B", unsigned char); +define_format_code("h", short); +define_format_code("H", unsigned short); +define_format_code("i", int); +define_format_code("I", unsigned int); +define_format_code("l", long); +define_format_code("L", unsigned long); +define_format_code("q", long long); +define_format_code("Q", unsigned long long); +define_format_code("f", float); +define_format_code("d", double); + +#endif // HAVE_PYTHON + #include "pointerToArray.I" -#endif +#endif // HAVE_POINTERTOARRAY_H diff --git a/panda/src/express/virtualFileSystem.cxx b/panda/src/express/virtualFileSystem.cxx index c0d85bac0d..69a32bd794 100644 --- a/panda/src/express/virtualFileSystem.cxx +++ b/panda/src/express/virtualFileSystem.cxx @@ -920,41 +920,6 @@ get_global_ptr() { return _global_ptr; } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: VirtualFileSystem::__py__read_file -// Access: Published -// Description: Convenience function; returns the entire contents of -// the indicated file as a string (or as a bytes object, -// in Python 3). -// -// This variant on read_file() is implemented directly -// for Python, as a small optimization, to avoid the -// double-construction of a string object that would be -// otherwise required for the return value. -//////////////////////////////////////////////////////////////////// -PyObject *VirtualFileSystem:: -__py__read_file(const Filename &filename, bool auto_unwrap) const { - pvector pv; - bool okflag = read_file(filename, pv, auto_unwrap); - nassertr(okflag, NULL); - -#if PY_MAJOR_VERSION >= 3 - if (pv.empty()) { - return PyBytes_FromStringAndSize("", 0); - } else { - return PyBytes_FromStringAndSize((const char *)&pv[0], pv.size()); - } -#else - if (pv.empty()) { - return PyString_FromStringAndSize("", 0); - } else { - return PyString_FromStringAndSize((const char *)&pv[0], pv.size()); - } -#endif -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: VirtualFileSystem::open_read_file // Access: Published @@ -1007,38 +972,6 @@ close_read_file(istream *stream) { } } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: VirtualFileSystem::__py__write_file -// Access: Published -// Description: Convenience function; writes the entire contents of -// the indicated file as a string. -// -// This variant on write_file() is implemented directly -// for Python, as a small optimization, to avoid the -// double-construction of a string object that would be -// otherwise required. -//////////////////////////////////////////////////////////////////// -PyObject *VirtualFileSystem:: -__py__write_file(const Filename &filename, PyObject *data, bool auto_wrap) { - char *buffer; - Py_ssize_t length; - -#if PY_MAJOR_VERSION >= 3 - if (PyBytes_AsStringAndSize(data, &buffer, &length) == -1) { - return NULL; - } -#else - if (PyString_AsStringAndSize(data, &buffer, &length) == -1) { - return NULL; - } -#endif - - bool result = write_file(filename, (const unsigned char *)buffer, length, auto_wrap); - return PyBool_FromLong(result); -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: VirtualFileSystem::open_write_file // Access: Published diff --git a/panda/src/express/virtualFileSystem.h b/panda/src/express/virtualFileSystem.h index 48b849b3fc..c497aaa86d 100644 --- a/panda/src/express/virtualFileSystem.h +++ b/panda/src/express/virtualFileSystem.h @@ -98,18 +98,11 @@ PUBLISHED: static VirtualFileSystem *get_global_ptr(); -#ifdef HAVE_PYTHON - BLOCKING PyObject *__py__read_file(const Filename &filename, bool auto_unwrap) const; -#endif // HAVE_PYTHON - BLOCKING INLINE string read_file(const Filename &filename, bool auto_unwrap) const; - + EXTENSION(BLOCKING PyObject *read_file(const Filename &filename, bool auto_unwrap) const); BLOCKING istream *open_read_file(const Filename &filename, bool auto_unwrap) const; BLOCKING static void close_read_file(istream *stream); -#ifdef HAVE_PYTHON - BLOCKING PyObject *__py__write_file(const Filename &filename, PyObject *data, bool auto_wrap); -#endif // HAVE_PYTHON - BLOCKING INLINE bool write_file(const Filename &filename, const string &data, bool auto_wrap); + EXTENSION(BLOCKING PyObject *write_file(const Filename &filename, PyObject *data, bool auto_wrap)); BLOCKING ostream *open_write_file(const Filename &filename, bool auto_wrap, bool truncate); BLOCKING ostream *open_append_file(const Filename &filename); BLOCKING static void close_write_file(ostream *stream); @@ -119,6 +112,10 @@ PUBLISHED: BLOCKING static void close_read_write_file(iostream *stream); public: + // We provide Python versions of these as efficient extension methods, above. + BLOCKING INLINE string read_file(const Filename &filename, bool auto_unwrap) const; + BLOCKING INLINE bool write_file(const Filename &filename, const string &data, bool auto_wrap); + bool atomic_compare_and_exchange_contents(const Filename &filename, string &orig_contents, const string &old_contents, const string &new_contents); bool atomic_read_contents(const Filename &filename, string &contents) const; diff --git a/panda/src/express/virtualFileSystem_ext.cxx b/panda/src/express/virtualFileSystem_ext.cxx new file mode 100644 index 0000000000..c5981b347a --- /dev/null +++ b/panda/src/express/virtualFileSystem_ext.cxx @@ -0,0 +1,82 @@ +// Filename: virtualFileSystem_ext.cxx +// Created by: rdb (12Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "virtualFileSystem_ext.h" + +#ifdef HAVE_PYTHON + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileSystem::read_file +// Access: Published +// Description: Convenience function; returns the entire contents of +// the indicated file as a string (or as a bytes object, +// in Python 3). +// +// This variant on read_file() is implemented directly +// for Python, as a small optimization, to avoid the +// double-construction of a string object that would be +// otherwise required for the return value. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +read_file(const Filename &filename, bool auto_unwrap) const { + pvector pv; + bool okflag = _this->read_file(filename, pv, auto_unwrap); + nassertr(okflag, NULL); + +#if PY_MAJOR_VERSION >= 3 + if (pv.empty()) { + return PyBytes_FromStringAndSize("", 0); + } else { + return PyBytes_FromStringAndSize((const char *)&pv[0], pv.size()); + } +#else + if (pv.empty()) { + return PyString_FromStringAndSize("", 0); + } else { + return PyString_FromStringAndSize((const char *)&pv[0], pv.size()); + } +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileSystem::write_file +// Access: Published +// Description: Convenience function; writes the entire contents of +// the indicated file as a string. +// +// This variant on write_file() is implemented directly +// for Python, as a small optimization, to avoid the +// double-construction of a string object that would be +// otherwise required. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +write_file(const Filename &filename, PyObject *data, bool auto_wrap) { + char *buffer; + Py_ssize_t length; + +#if PY_MAJOR_VERSION >= 3 + if (PyBytes_AsStringAndSize(data, &buffer, &length) == -1) { + return NULL; + } +#else + if (PyString_AsStringAndSize(data, &buffer, &length) == -1) { + return NULL; + } +#endif + + bool result = _this->write_file(filename, (const unsigned char *)buffer, length, auto_wrap); + return PyBool_FromLong(result); +} + +#endif // HAVE_PYTHOS diff --git a/panda/src/express/virtualFileSystem_ext.h b/panda/src/express/virtualFileSystem_ext.h new file mode 100644 index 0000000000..73190966df --- /dev/null +++ b/panda/src/express/virtualFileSystem_ext.h @@ -0,0 +1,41 @@ +// Filename: virtualFileSystem_ext.h +// Created by: rdb (12Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef VIRTUALFILESYSTEM_EXT_H +#define VIRTUALFILESYSTEM_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "virtualFileSystem.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// VirtualFileSystem, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + PyObject *read_file(Filename const &filename, bool auto_unwrap) const; + PyObject *write_file(Filename const &filename, PyObject *data, bool auto_wrap); +}; + +#endif // HAVE_PYTHON + +#endif // VIRTUALFILESYSTEM_EXT_H diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index 3b0818d66e..547c12cea6 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -30,6 +30,7 @@ geomLinestrips.h \ geomPoints.h \ geomVertexArrayData.h geomVertexArrayData.I \ + geomVertexArrayData_ext.h geomVertexArrayData_ext.cxx \ geomVertexArrayFormat.h geomVertexArrayFormat.I \ geomCacheEntry.h geomCacheEntry.I \ geomCacheManager.h geomCacheManager.I \ diff --git a/panda/src/gobj/geomVertexArrayData.h b/panda/src/gobj/geomVertexArrayData.h index 53ef9695e0..d7682ad979 100644 --- a/panda/src/gobj/geomVertexArrayData.h +++ b/panda/src/gobj/geomVertexArrayData.h @@ -114,6 +114,10 @@ PUBLISHED: static void lru_epoch(); INLINE static VertexDataBook &get_book(); + EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags)); + EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const); + EXTENSION(void __releasebuffer__(PyObject *self, Py_buffer *view) const); + public: virtual void evict_lru(); diff --git a/panda/src/gobj/geomVertexArrayData_ext.cxx b/panda/src/gobj/geomVertexArrayData_ext.cxx new file mode 100644 index 0000000000..edc95cd0ae --- /dev/null +++ b/panda/src/gobj/geomVertexArrayData_ext.cxx @@ -0,0 +1,167 @@ +// Filename: geomVertexArrayData_ext.I +// Created by: rdb (05Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "geomVertexArrayData_ext.h" + +struct InternalBufferData { + CPT(GeomVertexArrayDataHandle) _handle; + Py_ssize_t _num_rows; + Py_ssize_t _stride; + string _format; +}; + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexArrayData::__getbuffer__ +// Access: Published +// Description: This is used to implement the buffer protocol, in +// order to allow efficient access to the array data +// through a Python multiview object. +//////////////////////////////////////////////////////////////////// +int Extension:: +__getbuffer__(PyObject *self, Py_buffer *view, int flags) { + + PT(GeomVertexArrayDataHandle) handle = _this->modify_handle(); + CPT(GeomVertexArrayFormat) format = handle->get_array_format(); + + int row_size; + bool pad_fmt; + + if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { + // The consumer is fine with having a stride value. + row_size = format->get_total_bytes(); + pad_fmt = false; + } else { + // The consumer expects a contiguous buffer. Give the + // stride as row size, and pad the format with extra bytes. + row_size = format->get_stride(); + pad_fmt = true; + } + + InternalBufferData *data = new InternalBufferData; + data->_handle = handle; + data->_num_rows = handle->get_num_rows(); + data->_stride = format->get_stride(); + data->_format = format->get_format_string(pad_fmt); + + view->internal = (void*) data; + + if (self != NULL) { + Py_INCREF(self); + } + view->obj = self; + view->buf = (void*) handle->get_write_pointer(); + view->len = row_size * handle->get_num_rows(); + view->readonly = 0; + view->itemsize = row_size; + view->format = NULL; + if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { + view->format = (char*) data->_format.c_str(); + } + view->ndim = 1; + view->shape = NULL; + if ((flags & PyBUF_ND) == PyBUF_ND) { + view->shape = &data->_num_rows; + } + view->strides = NULL; + if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { + view->strides = &data->_stride; + } + view->suboffsets = NULL; + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexArrayData::__getbuffer__ +// Access: Published +// Description: This is the const version of __getbuffer__, which +// does not support writing. +//////////////////////////////////////////////////////////////////// +int Extension:: +__getbuffer__(PyObject *self, Py_buffer *view, int flags) const { + + if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) { + PyErr_SetString(PyExc_BufferError, + "Object is not writable."); + return -1; + } + + CPT(GeomVertexArrayDataHandle) handle = _this->get_handle(); + CPT(GeomVertexArrayFormat) format = handle->get_array_format(); + + int row_size; + bool pad_fmt; + + if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { + // The consumer is fine with having a stride value. + row_size = format->get_total_bytes(); + pad_fmt = false; + } else { + // The consumer expects a contiguous buffer. Give the + // stride as row size, and pad the format with extra bytes. + row_size = format->get_stride(); + pad_fmt = true; + } + + InternalBufferData *data = new InternalBufferData; + data->_handle = handle; + data->_num_rows = handle->get_num_rows(); + data->_stride = format->get_stride(); + data->_format = format->get_format_string(pad_fmt); + + view->internal = (void*) data; + + if (self != NULL) { + Py_INCREF(self); + } + view->obj = self; + view->buf = (void*) handle->get_read_pointer(true); + view->len = row_size * handle->get_num_rows(); + view->readonly = 1; + view->itemsize = row_size; + view->format = NULL; + if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { + view->format = (char*) data->_format.c_str(); + } + view->ndim = 1; + view->shape = NULL; + if ((flags & PyBUF_ND) == PyBUF_ND) { + view->shape = &data->_num_rows; + } + view->strides = NULL; + if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { + view->strides = &data->_stride; + } + view->suboffsets = NULL; + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexArrayData::__releasebuffer__ +// Access: Published +// Description: Releases the buffer allocated by __getbuffer__. +//////////////////////////////////////////////////////////////////// +void Extension:: +__releasebuffer__(PyObject *self, Py_buffer *view) const { + // Note: PyBuffer_Release automatically decrements view->obj. + + InternalBufferData *data; + data = (InternalBufferData *) view->internal; + if (data == NULL) { + return; + } + delete data; + view->internal = NULL; +} diff --git a/panda/src/gobj/geomVertexArrayData_ext.h b/panda/src/gobj/geomVertexArrayData_ext.h new file mode 100644 index 0000000000..826e39ae1f --- /dev/null +++ b/panda/src/gobj/geomVertexArrayData_ext.h @@ -0,0 +1,42 @@ +// Filename: geomVertexArrayData_ext.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef GEOMVERTEXARRAYDATA_EXT_H +#define GEOMVERTEXARRAYDATA_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "geomVertexArrayData.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// GeomVertexArrayData, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + int __getbuffer__(PyObject *self, Py_buffer *view, int flags); + int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const; + void __releasebuffer__(PyObject *self, Py_buffer *view) const; +}; + +#endif // HAVE_PYTHON + +#endif // GEOMVERTEXARRAYDATA_EXT_H diff --git a/panda/src/gobj/geomVertexArrayFormat.cxx b/panda/src/gobj/geomVertexArrayFormat.cxx index 809771788e..1c2877b1f3 100644 --- a/panda/src/gobj/geomVertexArrayFormat.cxx +++ b/panda/src/gobj/geomVertexArrayFormat.cxx @@ -578,6 +578,83 @@ write_with_data(ostream &out, int indent_level, } } +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexArrayFormat::get_format_string +// Access: Published +// Description: Returns a string with format codes representing the +// exact memory layout of the columns in memory, as +// understood by Python's struct module. +// If pad is true, extra padding bytes are added to +// the end as 'x' characters as needed. +//////////////////////////////////////////////////////////////////// +string GeomVertexArrayFormat:: +get_format_string(bool pad) const { + consider_sort_columns(); + + int row_size; + if (pad) { + row_size = get_stride(); + } else { + row_size = get_total_bytes(); + } + + // Synthesize the format string. + char *fmt = (char*) malloc(row_size + 1); + memset((void*) fmt, 0, row_size + 1); + int fi = 0; + int offset = 0; + + for (int ci = 0; ci < get_num_columns(); ++ci) { + const GeomVertexColumn *column = get_column(ci); + + if (offset < column->get_start()) { + // Add padding bytes to fill the gap. + int pad = column->get_start() - offset; + memset((void*) (fmt + fi), 'x', pad); + fi += pad; + offset += pad; + } + + char fmt_code = 'x'; + switch (column->get_numeric_type()) { + case NT_uint8: + fmt_code = 'B'; + break; + case NT_uint16: + fmt_code = 'H'; + break; + case NT_uint32: + case NT_packed_dcba: + case NT_packed_dabc: + fmt_code = 'I'; + break; + case NT_float32: + fmt_code = 'f'; + break; + case NT_float64: + fmt_code = 'd'; + break; + default: + gobj_cat.error() + << "Unknown numeric type " << column->get_numeric_type() << "!\n"; + return NULL; + } + memset((void*) (fmt + fi), fmt_code, column->get_num_components()); + offset += column->get_total_bytes(); + fi += column->get_num_components(); + } + + if (offset < row_size) { + // Add padding bytes. + int pad = row_size - offset; + memset((void*) (fmt + fi), 'x', pad); + } + + string fmt_string (fmt); + free(fmt); + return fmt_string; +} + //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::compare_to // Access: Public diff --git a/panda/src/gobj/geomVertexArrayFormat.h b/panda/src/gobj/geomVertexArrayFormat.h index 2a8867428b..56a9d066ab 100644 --- a/panda/src/gobj/geomVertexArrayFormat.h +++ b/panda/src/gobj/geomVertexArrayFormat.h @@ -115,6 +115,8 @@ PUBLISHED: void write_with_data(ostream &out, int indent_level, const GeomVertexArrayData *array_data) const; + string get_format_string(bool pad = true) const; + public: int compare_to(const GeomVertexArrayFormat &other) const; diff --git a/panda/src/linmath/Sources.pp b/panda/src/linmath/Sources.pp index b366d79060..9c5a1c9548 100644 --- a/panda/src/linmath/Sources.pp +++ b/panda/src/linmath/Sources.pp @@ -15,7 +15,7 @@ coordinateSystem.h dbl2fltnames.h dblnames.h \ deg_2_rad.h deg_2_rad.I \ flt2dblnames.h fltnames.h lcast_to.h lcast_to_src.h \ - lcast_to_src.I lmatrix.h lmatrix_ext.I lmatrix3_src.I \ + lcast_to_src.I lmatrix.h lmatrix_ext.h lmatrix3_src.I \ lmatrix3_src.cxx lmatrix3_src.h lmatrix4_src.I \ lmatrix4_src.cxx lmatrix4_src.h lorientation.h \ lorientation_src.I lorientation_src.cxx lorientation_src.h \ @@ -37,12 +37,12 @@ lvector3.h lvector3_src.I lvector3_src.cxx lvector3_src.h \ lvector4.h lvector4_src.I lvector4_src.cxx lvector4_src.h \ lvector4.h lvector4_src.I lvector4_src.cxx lvector4_src.h \ - lvecBase2_ext.I lvecBase3_ext.I lvecBase4_ext.I \ - lpoint2_ext.I lpoint3_ext.I lpoint4_ext.I \ - lvector2_ext.I lvector3_ext.I lvector4_ext.I \ + lvecBase2_ext.h lvecBase3_ext.h lvecBase4_ext.h \ + lpoint2_ext.h lpoint3_ext.h lpoint4_ext.h \ + lvector2_ext.h lvector3_ext.h lvector4_ext.h \ mathNumbers.h mathNumbers.I - #define INCLUDED_SOURCES \ + #define INCLUDED_SOURCES \ compose_matrix.cxx config_linmath.cxx coordinateSystem.cxx \ lmatrix.cxx \ lorientation.cxx lpoint2.cxx \ diff --git a/panda/src/linmath/lmatrix3_ext_src.I b/panda/src/linmath/lmatrix3_ext_src.I index ba87c2f94e..ec359f6c40 100644 --- a/panda/src/linmath/lmatrix3_ext_src.I +++ b/panda/src/linmath/lmatrix3_ext_src.I @@ -18,10 +18,10 @@ // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_NESTED_METHOD_ARGS(FLOATNAME(LMatrix3), Row, -__setitem__, int i, FLOATTYPE v) { +INLINE_LINMATH void Extension:: +__setitem__(int i, FLOATTYPE v) { nassertv(i >= 0 && i < 3); - this->_row[i] = v; + _this->_row[i] = v; } //////////////////////////////////////////////////////////////////// @@ -30,8 +30,8 @@ __setitem__, int i, FLOATTYPE v) { // Description: This special Python method is implement to provide // support for the pickle module. //////////////////////////////////////////////////////////////////// -PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LMatrix3), -__reduce__, PyObject *self) { +INLINE_LINMATH PyObject *Extension:: +__reduce__(PyObject *self) const { // We should return at least a 2-tuple, (Class, (args)): the // necessary class object whose constructor we should call // (e.g. this), and the arguments necessary to reconstruct this @@ -42,9 +42,9 @@ __reduce__, PyObject *self) { } PyObject *result = Py_BuildValue("(O(fffffffff))", this_class, - this->_m(0, 0), this->_m(0, 1), this->_m(0, 2), - this->_m(1, 0), this->_m(1, 1), this->_m(1, 2), - this->_m(2, 0), this->_m(2, 1), this->_m(2, 2)); + _this->_m(0, 0), _this->_m(0, 1), _this->_m(0, 2), + _this->_m(1, 0), _this->_m(1, 1), _this->_m(1, 2), + _this->_m(2, 0), _this->_m(2, 1), _this->_m(2, 2)); Py_DECREF(this_class); return result; @@ -55,19 +55,19 @@ __reduce__, PyObject *self) { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -void EXT_CONST_METHOD_ARGS(FLOATNAME(LMatrix3), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_m(0, 0)) << ", " - << MAYBE_ZERO(this->_m(0, 1)) << ", " - << MAYBE_ZERO(this->_m(0, 2)) << ", " + << MAYBE_ZERO(_this->_m(0, 0)) << ", " + << MAYBE_ZERO(_this->_m(0, 1)) << ", " + << MAYBE_ZERO(_this->_m(0, 2)) << ", " - << MAYBE_ZERO(this->_m(1, 0)) << ", " - << MAYBE_ZERO(this->_m(1, 1)) << ", " - << MAYBE_ZERO(this->_m(1, 2)) << ", " + << MAYBE_ZERO(_this->_m(1, 0)) << ", " + << MAYBE_ZERO(_this->_m(1, 1)) << ", " + << MAYBE_ZERO(_this->_m(1, 2)) << ", " - << MAYBE_ZERO(this->_m(2, 0)) << ", " - << MAYBE_ZERO(this->_m(2, 1)) << ", " - << MAYBE_ZERO(this->_m(2, 2)) << ")"; + << MAYBE_ZERO(_this->_m(2, 0)) << ", " + << MAYBE_ZERO(_this->_m(2, 1)) << ", " + << MAYBE_ZERO(_this->_m(2, 2)) << ")"; } diff --git a/panda/src/linmath/lmatrix3_ext_src.h b/panda/src/linmath/lmatrix3_ext_src.h new file mode 100644 index 0000000000..5be62dc1fb --- /dev/null +++ b/panda/src/linmath/lmatrix3_ext_src.h @@ -0,0 +1,41 @@ +// Filename: lmatrix3_ext_src.h +// Created by: rdb (12Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LMatrix3::Row, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH void __setitem__(int i, FLOATTYPE v); +}; + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LMatrix3, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__reduce__(PyObject *self) const; + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +#include "lmatrix3_ext_src.I" diff --git a/panda/src/linmath/lmatrix3_src.h b/panda/src/linmath/lmatrix3_src.h index 2a510ed864..ab4fc12a7c 100644 --- a/panda/src/linmath/lmatrix3_src.h +++ b/panda/src/linmath/lmatrix3_src.h @@ -63,7 +63,7 @@ PUBLISHED: FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22); ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix3)); - EXTENSION(PyObject *__reduce__(PyObject *self) const); + EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const); void fill(FLOATTYPE fill_value); INLINE_LINMATH void set( @@ -283,7 +283,7 @@ PUBLISHED: void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; - EXTENSION(void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const; void generate_hash( diff --git a/panda/src/linmath/lmatrix4_ext_src.I b/panda/src/linmath/lmatrix4_ext_src.I index 146a73f34d..91a8122426 100644 --- a/panda/src/linmath/lmatrix4_ext_src.I +++ b/panda/src/linmath/lmatrix4_ext_src.I @@ -18,10 +18,10 @@ // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_NESTED_METHOD_ARGS(FLOATNAME(LMatrix4), Row, -__setitem__, int i, FLOATTYPE v) { +INLINE_LINMATH void Extension:: +__setitem__(int i, FLOATTYPE v) { nassertv(i >= 0 && i < 4); - this->_row[i] = v; + _this->_row[i] = v; } //////////////////////////////////////////////////////////////////// @@ -30,8 +30,8 @@ __setitem__, int i, FLOATTYPE v) { // Description: This special Python method is implement to provide // support for the pickle module. //////////////////////////////////////////////////////////////////// -PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LMatrix4), -__reduce__, PyObject *self) { +INLINE_LINMATH PyObject *Extension:: +__reduce__(PyObject *self) const { // We should return at least a 2-tuple, (Class, (args)): the // necessary class object whose constructor we should call // (e.g. this), and the arguments necessary to reconstruct this @@ -42,10 +42,10 @@ __reduce__, PyObject *self) { } PyObject *result = Py_BuildValue("(O(ffffffffffffffff))", this_class, - this->_m(0, 0), this->_m(0, 1), this->_m(0, 2), this->_m(0, 3), - this->_m(1, 0), this->_m(1, 1), this->_m(1, 2), this->_m(1, 3), - this->_m(2, 0), this->_m(2, 1), this->_m(2, 2), this->_m(2, 3), - this->_m(3, 0), this->_m(3, 1), this->_m(3, 2), this->_m(3, 3)); + _this->_m(0, 0), _this->_m(0, 1), _this->_m(0, 2), _this->_m(0, 3), + _this->_m(1, 0), _this->_m(1, 1), _this->_m(1, 2), _this->_m(1, 3), + _this->_m(2, 0), _this->_m(2, 1), _this->_m(2, 2), _this->_m(2, 3), + _this->_m(3, 0), _this->_m(3, 1), _this->_m(3, 2), _this->_m(3, 3)); Py_DECREF(this_class); return result; @@ -56,27 +56,27 @@ __reduce__, PyObject *self) { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -void EXT_CONST_METHOD_ARGS(FLOATNAME(LMatrix4), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_m(0, 0)) << ", " - << MAYBE_ZERO(this->_m(0, 1)) << ", " - << MAYBE_ZERO(this->_m(0, 2)) << ", " - << MAYBE_ZERO(this->_m(0, 3)) << ", " + << MAYBE_ZERO(_this->_m(0, 0)) << ", " + << MAYBE_ZERO(_this->_m(0, 1)) << ", " + << MAYBE_ZERO(_this->_m(0, 2)) << ", " + << MAYBE_ZERO(_this->_m(0, 3)) << ", " - << MAYBE_ZERO(this->_m(1, 0)) << ", " - << MAYBE_ZERO(this->_m(1, 1)) << ", " - << MAYBE_ZERO(this->_m(1, 2)) << ", " - << MAYBE_ZERO(this->_m(1, 3)) << ", " + << MAYBE_ZERO(_this->_m(1, 0)) << ", " + << MAYBE_ZERO(_this->_m(1, 1)) << ", " + << MAYBE_ZERO(_this->_m(1, 2)) << ", " + << MAYBE_ZERO(_this->_m(1, 3)) << ", " - << MAYBE_ZERO(this->_m(2, 0)) << ", " - << MAYBE_ZERO(this->_m(2, 1)) << ", " - << MAYBE_ZERO(this->_m(2, 2)) << ", " - << MAYBE_ZERO(this->_m(2, 3)) << ", " + << MAYBE_ZERO(_this->_m(2, 0)) << ", " + << MAYBE_ZERO(_this->_m(2, 1)) << ", " + << MAYBE_ZERO(_this->_m(2, 2)) << ", " + << MAYBE_ZERO(_this->_m(2, 3)) << ", " - << MAYBE_ZERO(this->_m(3, 0)) << ", " - << MAYBE_ZERO(this->_m(3, 1)) << ", " - << MAYBE_ZERO(this->_m(3, 2)) << ", " - << MAYBE_ZERO(this->_m(3, 3)) << ")"; + << MAYBE_ZERO(_this->_m(3, 0)) << ", " + << MAYBE_ZERO(_this->_m(3, 1)) << ", " + << MAYBE_ZERO(_this->_m(3, 2)) << ", " + << MAYBE_ZERO(_this->_m(3, 3)) << ")"; } diff --git a/panda/src/linmath/lmatrix4_ext_src.h b/panda/src/linmath/lmatrix4_ext_src.h new file mode 100644 index 0000000000..de97a6bb94 --- /dev/null +++ b/panda/src/linmath/lmatrix4_ext_src.h @@ -0,0 +1,41 @@ +// Filename: lmatrix4_ext_src.h +// Created by: rdb (12Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LMatrix4::Row, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH void __setitem__(int i, FLOATTYPE v); +}; + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LMatrix4, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__reduce__(PyObject *self) const; + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +#include "lmatrix4_ext_src.I" diff --git a/panda/src/linmath/lmatrix4_src.h b/panda/src/linmath/lmatrix4_src.h index d7a445ccde..367ea7c441 100644 --- a/panda/src/linmath/lmatrix4_src.h +++ b/panda/src/linmath/lmatrix4_src.h @@ -63,7 +63,7 @@ PUBLISHED: FLOATTYPE e30, FLOATTYPE e31, FLOATTYPE e32, FLOATTYPE e33); ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix4)); - EXTENSION(PyObject *__reduce__(PyObject *self) const); + EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const); // Construct a 4x4 matrix given a 3x3 rotation matrix and an optional // translation component. @@ -257,7 +257,7 @@ PUBLISHED: void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; - EXTENSION(void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const; void generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE scale) const; diff --git a/panda/src/linmath/lmatrix_ext.I b/panda/src/linmath/lmatrix_ext.h similarity index 66% rename from panda/src/linmath/lmatrix_ext.I rename to panda/src/linmath/lmatrix_ext.h index 21dac41d92..e6012fa14f 100644 --- a/panda/src/linmath/lmatrix_ext.I +++ b/panda/src/linmath/lmatrix_ext.h @@ -1,5 +1,5 @@ -// Filename: lmatrix_ext.I -// Created by: rdb (02Jan11) +// Filename: lmatrix_ext.h +// Created by: rdb (13Sep13) // //////////////////////////////////////////////////////////////////// // @@ -12,12 +12,18 @@ // //////////////////////////////////////////////////////////////////// +#ifndef LMATRIX_EXT_H +#define LMATRIX_EXT_H + #include "lmatrix.h" +#include "extension.h" #include "fltnames.h" -#include "lmatrix3_ext_src.I" -#include "lmatrix4_ext_src.I" +#include "lmatrix3_ext_src.h" +#include "lmatrix4_ext_src.h" #include "dblnames.h" -#include "lmatrix3_ext_src.I" -#include "lmatrix4_ext_src.I" +#include "lmatrix3_ext_src.h" +#include "lmatrix4_ext_src.h" + +#endif diff --git a/panda/src/linmath/lpoint2_ext.I b/panda/src/linmath/lpoint2_ext.h similarity index 73% rename from panda/src/linmath/lpoint2_ext.I rename to panda/src/linmath/lpoint2_ext.h index b48ea4c573..006697f0c0 100644 --- a/panda/src/linmath/lpoint2_ext.I +++ b/panda/src/linmath/lpoint2_ext.h @@ -1,5 +1,5 @@ // Filename: lpoint2_ext.I -// Created by: rdb (02Jan11) +// Created by: rdb (13Sep13) // //////////////////////////////////////////////////////////////////// // @@ -12,11 +12,18 @@ // //////////////////////////////////////////////////////////////////// +#ifndef LPOINT2_EXT_H +#define LPOINT2_EXT_H + #include "lpoint2.h" +#include "extension.h" + +#include "lvecBase2_ext.h" #include "fltnames.h" -#include "lpoint2_ext_src.I" +#include "lpoint2_ext_src.h" #include "dblnames.h" -#include "lpoint2_ext_src.I" +#include "lpoint2_ext_src.h" +#endif diff --git a/panda/src/linmath/lpoint2_ext_src.I b/panda/src/linmath/lpoint2_ext_src.I index 57d5eea021..b5716fa071 100644 --- a/panda/src/linmath/lpoint2_ext_src.I +++ b/panda/src/linmath/lpoint2_ext_src.I @@ -12,9 +12,10 @@ // //////////////////////////////////////////////////////////////////// - #ifndef CPPPARSER IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint2); +IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint3); +IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint4); #endif //////////////////////////////////////////////////////////////////// @@ -22,11 +23,11 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint2); // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_CONST_METHOD_ARGS(FLOATNAME(LPoint2), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_v(0)) << ", " - << MAYBE_ZERO(this->_v(1)) << ")"; + << MAYBE_ZERO(_this->_v(0)) << ", " + << MAYBE_ZERO(_this->_v(1)) << ")"; } //////////////////////////////////////////////////////////////////// @@ -34,8 +35,8 @@ python_repr, ostream &out, const string &class_name) { // Access: Published // Description: This is used to implement swizzle masks. //////////////////////////////////////////////////////////////////// -INLINE PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LPoint2), -__getattr__, const string &attr_name) { +INLINE_LINMATH PyObject *Extension:: +__getattr__(const string &attr_name) const { // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { if (*it != 'x' && *it != 'y') { @@ -43,28 +44,43 @@ __getattr__, const string &attr_name) { } } - if (attr_name.size() == 1) { - return PyFloat_FromDouble(this->_v(attr_name[0] - 'x')); + switch (attr_name.size()) { + case 1: + return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); - } else if (attr_name.size() == 2) { - FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint2), true, false); + case 2: { + FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint2), true, false); + + } case 3: { + FLOATNAME(LPoint3) *vec = new FLOATNAME(LPoint3); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint3), true, false); + + } case 4: { + FLOATNAME(LPoint4) *vec = new FLOATNAME(LPoint4); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + vec->_v(3) = _this->_v(attr_name[3] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint4), true, false); + } } return NULL; } -int EXT_METHOD_ARGS(FLOATNAME(LVecBase2), __setattr__, PyObject*, const string&, PyObject*); - //////////////////////////////////////////////////////////////////// // Function: LPoint2::__setattr__ // Access: Published // Description: This is used to implement write masks. //////////////////////////////////////////////////////////////////// -INLINE int EXT_METHOD_ARGS(FLOATNAME(LPoint2), -__setattr__, PyObject *self, const string &attr_name, PyObject *assign) { - return CALL_EXT_METHOD(FLOATNAME(LVecBase2), __setattr__, this, self, attr_name, assign); +INLINE_LINMATH int Extension:: +__setattr__(PyObject *self, const string &attr_name, PyObject *assign) { + // Upcall to LVecBase2. + return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); } - diff --git a/panda/src/linmath/lpoint2_ext_src.h b/panda/src/linmath/lpoint2_ext_src.h new file mode 100644 index 0000000000..c706bcc402 --- /dev/null +++ b/panda/src/linmath/lpoint2_ext_src.h @@ -0,0 +1,30 @@ +// Filename: lpoint2_ext_src.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LPoint2, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; + INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +#include "lpoint2_ext_src.I" diff --git a/panda/src/linmath/lpoint2_src.h b/panda/src/linmath/lpoint2_src.h index 02b26fc8f5..7d726e4f33 100644 --- a/panda/src/linmath/lpoint2_src.h +++ b/panda/src/linmath/lpoint2_src.h @@ -26,8 +26,8 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint2)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LPoint2)(FLOATTYPE x, FLOATTYPE y); - EXTENSION(PyObject *__getattr__(const string &attr_name) const); - EXTENSION(int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); + EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); + EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); INLINE_LINMATH static const FLOATNAME(LPoint2) &zero(); INLINE_LINMATH static const FLOATNAME(LPoint2) &unit_x(); diff --git a/panda/src/linmath/lpoint3_ext.I b/panda/src/linmath/lpoint3_ext.h similarity index 73% rename from panda/src/linmath/lpoint3_ext.I rename to panda/src/linmath/lpoint3_ext.h index 6f829d43b2..0f4c860b9e 100644 --- a/panda/src/linmath/lpoint3_ext.I +++ b/panda/src/linmath/lpoint3_ext.h @@ -1,5 +1,5 @@ // Filename: lpoint3_ext.I -// Created by: rdb (02Jan11) +// Created by: rdb (13Sep13) // //////////////////////////////////////////////////////////////////// // @@ -12,11 +12,18 @@ // //////////////////////////////////////////////////////////////////// +#ifndef LPOINT3_EXT_H +#define LPOINT3_EXT_H + #include "lpoint3.h" +#include "extension.h" + +#include "lvecBase3_ext.h" #include "fltnames.h" -#include "lpoint3_ext_src.I" +#include "lpoint3_ext_src.h" #include "dblnames.h" -#include "lpoint3_ext_src.I" +#include "lpoint3_ext_src.h" +#endif diff --git a/panda/src/linmath/lpoint3_ext_src.I b/panda/src/linmath/lpoint3_ext_src.I index 5f3880e8e9..92178755e6 100644 --- a/panda/src/linmath/lpoint3_ext_src.I +++ b/panda/src/linmath/lpoint3_ext_src.I @@ -12,10 +12,10 @@ // //////////////////////////////////////////////////////////////////// - #ifndef CPPPARSER IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint2); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint3); +IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint4); #endif //////////////////////////////////////////////////////////////////// @@ -23,12 +23,12 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint3); // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_CONST_METHOD_ARGS(FLOATNAME(LPoint3), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_v(0)) << ", " - << MAYBE_ZERO(this->_v(1)) << ", " - << MAYBE_ZERO(this->_v(2)) << ")"; + << MAYBE_ZERO(_this->_v(0)) << ", " + << MAYBE_ZERO(_this->_v(1)) << ", " + << MAYBE_ZERO(_this->_v(2)) << ")"; } //////////////////////////////////////////////////////////////////// @@ -36,8 +36,8 @@ python_repr, ostream &out, const string &class_name) { // Access: Published // Description: This is used to implement swizzle masks. //////////////////////////////////////////////////////////////////// -PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LPoint3), -__getattr__, const string &attr_name) { +INLINE_LINMATH PyObject *Extension:: +__getattr__(const string &attr_name) const { // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { if (*it < 'x' || *it > 'z') { @@ -45,35 +45,43 @@ __getattr__, const string &attr_name) { } } - if (attr_name.size() == 1) { - return PyFloat_FromDouble(this->_v(attr_name[0] - 'x')); + switch (attr_name.size()) { + case 1: + return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); - } else if (attr_name.size() == 2) { - FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint2), true, false); + case 2: { + FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint2), true, false); - } else if (attr_name.size() == 3) { - FLOATNAME(LPoint3) *vec = new FLOATNAME(LPoint3); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - vec->_v(2) = this->_v(attr_name[2] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint3), true, false); + } case 3: { + FLOATNAME(LPoint3) *vec = new FLOATNAME(LPoint3); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint3), true, false); + + } case 4: { + FLOATNAME(LPoint4) *vec = new FLOATNAME(LPoint4); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + vec->_v(3) = _this->_v(attr_name[3] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint4), true, false); + } } return NULL; } -int EXT_METHOD_ARGS(FLOATNAME(LVecBase3), __setattr__, PyObject*, const string&, PyObject*); - //////////////////////////////////////////////////////////////////// // Function: LPoint3::__setattr__ // Access: Published // Description: This is used to implement write masks. //////////////////////////////////////////////////////////////////// -INLINE int EXT_METHOD_ARGS(FLOATNAME(LPoint3), -__setattr__, PyObject *self, const string &attr_name, PyObject *assign) { - return CALL_EXT_METHOD(FLOATNAME(LVecBase3), __setattr__, this, self, attr_name, assign); +INLINE_LINMATH int Extension:: +__setattr__(PyObject *self, const string &attr_name, PyObject *assign) { + // Upcall to LVecBase2. + return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); } - diff --git a/panda/src/linmath/lpoint3_ext_src.h b/panda/src/linmath/lpoint3_ext_src.h new file mode 100644 index 0000000000..6afda96af6 --- /dev/null +++ b/panda/src/linmath/lpoint3_ext_src.h @@ -0,0 +1,30 @@ +// Filename: lpoint3_ext_src.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LPoint3, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; + INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +#include "lpoint3_ext_src.I" diff --git a/panda/src/linmath/lpoint3_src.h b/panda/src/linmath/lpoint3_src.h index 24c8e7eecb..ce1852bda5 100644 --- a/panda/src/linmath/lpoint3_src.h +++ b/panda/src/linmath/lpoint3_src.h @@ -31,8 +31,8 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint3)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LPoint3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z); - EXTENSION(PyObject *__getattr__(const string &attr_name) const); - EXTENSION(int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); + EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); + EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); INLINE_LINMATH static const FLOATNAME(LPoint3) &zero(); INLINE_LINMATH static const FLOATNAME(LPoint3) &unit_x(); diff --git a/panda/src/linmath/lpoint4_ext.I b/panda/src/linmath/lpoint4_ext.h similarity index 73% rename from panda/src/linmath/lpoint4_ext.I rename to panda/src/linmath/lpoint4_ext.h index 92f9dc5dba..ac51d90156 100644 --- a/panda/src/linmath/lpoint4_ext.I +++ b/panda/src/linmath/lpoint4_ext.h @@ -1,5 +1,5 @@ // Filename: lpoint4_ext.I -// Created by: rdb (02Jan11) +// Created by: rdb (13Sep13) // //////////////////////////////////////////////////////////////////// // @@ -12,11 +12,18 @@ // //////////////////////////////////////////////////////////////////// +#ifndef LPOINT4_EXT_H +#define LPOINT4_EXT_H + #include "lpoint4.h" +#include "extension.h" + +#include "lvecBase4_ext.h" #include "fltnames.h" -#include "lpoint4_ext_src.I" +#include "lpoint4_ext_src.h" #include "dblnames.h" -#include "lpoint4_ext_src.I" +#include "lpoint4_ext_src.h" +#endif diff --git a/panda/src/linmath/lpoint4_ext_src.I b/panda/src/linmath/lpoint4_ext_src.I index 62c0e4ff50..708150f52b 100644 --- a/panda/src/linmath/lpoint4_ext_src.I +++ b/panda/src/linmath/lpoint4_ext_src.I @@ -12,7 +12,6 @@ // //////////////////////////////////////////////////////////////////// - #ifndef CPPPARSER IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint2); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint3); @@ -24,13 +23,13 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint4); // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_CONST_METHOD_ARGS(FLOATNAME(LPoint4), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_v(0)) << ", " - << MAYBE_ZERO(this->_v(1)) << ", " - << MAYBE_ZERO(this->_v(2)) << ", " - << MAYBE_ZERO(this->_v(3)) << ")"; + << MAYBE_ZERO(_this->_v(0)) << ", " + << MAYBE_ZERO(_this->_v(1)) << ", " + << MAYBE_ZERO(_this->_v(2)) << ", " + << MAYBE_ZERO(_this->_v(3)) << ")"; } //////////////////////////////////////////////////////////////////// @@ -38,8 +37,8 @@ python_repr, ostream &out, const string &class_name) { // Access: Published // Description: This is used to implement swizzle masks. //////////////////////////////////////////////////////////////////// -INLINE PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LPoint4), -__getattr__, const string &attr_name) { +INLINE_LINMATH PyObject *Extension:: +__getattr__(const string &attr_name) const { // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { if (*it < 'w' || *it > 'z') { @@ -47,47 +46,47 @@ __getattr__, const string &attr_name) { } } - if (attr_name.size() == 1) { - if (attr_name[0] == 'w') { - return PyFloat_FromDouble(this->_v(3)); - } else { - return PyFloat_FromDouble(this->_v(attr_name[0] - 'x')); + switch (attr_name.size()) { + case 1: + if (attr_name[0] == 'w') { + return PyFloat_FromDouble(_this->_v(3)); + } else { + return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + } + + case 2: { + FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2); + vec->_v(0) = _this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); + vec->_v(1) = _this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint2), true, false); + + } case 3: { + FLOATNAME(LPoint3) *vec = new FLOATNAME(LPoint3); + vec->_v(0) = _this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); + vec->_v(1) = _this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); + vec->_v(2) = _this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint3), true, false); + + } case 4: { + FLOATNAME(LPoint4) *vec = new FLOATNAME(LPoint4); + vec->_v(0) = _this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); + vec->_v(1) = _this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); + vec->_v(2) = _this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); + vec->_v(3) = _this->_v((attr_name[3] == 'w') ? 3 : attr_name[3] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint4), true, false); } - - } else if (attr_name.size() == 2) { - FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2); - vec->_v(0) = this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); - vec->_v(1) = this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint2), true, false); - - } else if (attr_name.size() == 3) { - FLOATNAME(LPoint3) *vec = new FLOATNAME(LPoint3); - vec->_v(0) = this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); - vec->_v(1) = this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); - vec->_v(2) = this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint3), true, false); - - } else if (attr_name.size() == 4) { - FLOATNAME(LPoint4) *vec = new FLOATNAME(LPoint4); - vec->_v(0) = this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); - vec->_v(1) = this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); - vec->_v(2) = this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); - vec->_v(3) = this->_v((attr_name[3] == 'w') ? 3 : attr_name[3] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LPoint4), true, false); } return NULL; } -int EXT_METHOD_ARGS(FLOATNAME(LVecBase4), __setattr__, PyObject*, const string&, PyObject*); - //////////////////////////////////////////////////////////////////// // Function: LPoint4::__setattr__ // Access: Published // Description: This is used to implement write masks. //////////////////////////////////////////////////////////////////// -INLINE int EXT_METHOD_ARGS(FLOATNAME(LPoint4), -__setattr__, PyObject *self, const string &attr_name, PyObject *assign) { - return CALL_EXT_METHOD(FLOATNAME(LVecBase4), __setattr__, this, self, attr_name, assign); +INLINE_LINMATH int Extension:: +__setattr__(PyObject *self, const string &attr_name, PyObject *assign) { + // Upcall to LVecBase4. + return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); } - diff --git a/panda/src/linmath/lpoint4_ext_src.h b/panda/src/linmath/lpoint4_ext_src.h new file mode 100644 index 0000000000..c010159c55 --- /dev/null +++ b/panda/src/linmath/lpoint4_ext_src.h @@ -0,0 +1,30 @@ +// Filename: lpoint4_ext_src.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LPoint4, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; + INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +#include "lpoint4_ext_src.I" diff --git a/panda/src/linmath/lpoint4_src.h b/panda/src/linmath/lpoint4_src.h index f38ac9df1d..04404b8713 100644 --- a/panda/src/linmath/lpoint4_src.h +++ b/panda/src/linmath/lpoint4_src.h @@ -25,8 +25,8 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint4)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LPoint4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w); - EXTENSION(PyObject *__getattr__(const string &attr_name) const); - EXTENSION(int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); + EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); + EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); INLINE_LINMATH static const FLOATNAME(LPoint4) &zero(); INLINE_LINMATH static const FLOATNAME(LPoint4) &unit_x(); diff --git a/panda/src/linmath/lvecBase2_ext.I b/panda/src/linmath/lvecBase2_ext.h similarity index 75% rename from panda/src/linmath/lvecBase2_ext.I rename to panda/src/linmath/lvecBase2_ext.h index 368b09db09..59f06da699 100644 --- a/panda/src/linmath/lvecBase2_ext.I +++ b/panda/src/linmath/lvecBase2_ext.h @@ -1,5 +1,5 @@ // Filename: lvecBase2_ext.I -// Created by: rdb (02Jan11) +// Created by: rdb (13Sep13) // //////////////////////////////////////////////////////////////////// // @@ -12,11 +12,16 @@ // //////////////////////////////////////////////////////////////////// +#ifndef LVECBASE2_EXT_H +#define LVECBASE2_EXT_H + #include "lvecBase2.h" +#include "extension.h" #include "fltnames.h" -#include "lvecBase2_ext_src.I" +#include "lvecBase2_ext_src.h" #include "dblnames.h" -#include "lvecBase2_ext_src.I" +#include "lvecBase2_ext_src.h" +#endif diff --git a/panda/src/linmath/lvecBase2_ext_src.I b/panda/src/linmath/lvecBase2_ext_src.I index b5c50b34f4..6f8bef7585 100644 --- a/panda/src/linmath/lvecBase2_ext_src.I +++ b/panda/src/linmath/lvecBase2_ext_src.I @@ -24,10 +24,10 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_METHOD_ARGS(FLOATNAME(LVecBase2), -__setitem__, int i, FLOATTYPE v) { +INLINE_LINMATH void Extension:: +__setitem__(int i, FLOATTYPE v) { nassertv(i >= 0 && i < 2); - this->_v(i) = v; + _this->_v(i) = v; } //////////////////////////////////////////////////////////////////// @@ -35,11 +35,11 @@ __setitem__, int i, FLOATTYPE v) { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_CONST_METHOD_ARGS(FLOATNAME(LVecBase2), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_v(0)) << ", " - << MAYBE_ZERO(this->_v(1)) << ")"; + << MAYBE_ZERO(_this->_v(0)) << ", " + << MAYBE_ZERO(_this->_v(1)) << ")"; } //////////////////////////////////////////////////////////////////// @@ -48,8 +48,8 @@ python_repr, ostream &out, const string &class_name) { // Description: This special Python method is implement to provide // support for the pickle module. //////////////////////////////////////////////////////////////////// -INLINE PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LVecBase2), -__reduce__, PyObject *self) { +INLINE_LINMATH PyObject *Extension:: +__reduce__(PyObject *self) const { // We should return at least a 2-tuple, (Class, (args)): the // necessary class object whose constructor we should call // (e.g. this), and the arguments necessary to reconstruct this @@ -60,7 +60,7 @@ __reduce__, PyObject *self) { } PyObject *result = Py_BuildValue("(O(ff))", this_class, - (*this)[0], (*this)[1]); + (*_this)[0], (*_this)[1]); Py_DECREF(this_class); return result; } @@ -70,8 +70,8 @@ __reduce__, PyObject *self) { // Access: Published // Description: This is used to implement swizzle masks. //////////////////////////////////////////////////////////////////// -PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LVecBase2), -__getattr__, const string &attr_name) { +INLINE_LINMATH PyObject *Extension:: +__getattr__(const string &attr_name) const { // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { if (*it != 'x' && *it != 'y') { @@ -79,29 +79,31 @@ __getattr__, const string &attr_name) { } } - if (attr_name.size() == 1) { - return PyFloat_FromDouble(this->_v(attr_name[0] - 'x')); + switch (attr_name.size()) { + case 1: + return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); - } else if (attr_name.size() == 2) { - FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase2), true, false); + case 2: { + FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase2), true, false); - } else if (attr_name.size() == 3) { - FLOATNAME(LVecBase3) *vec = new FLOATNAME(LVecBase3); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - vec->_v(2) = this->_v(attr_name[2] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase3), true, false); + } case 3: { + FLOATNAME(LVecBase3) *vec = new FLOATNAME(LVecBase3); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase3), true, false); - } else if (attr_name.size() == 4) { - FLOATNAME(LVecBase4) *vec = new FLOATNAME(LVecBase4); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - vec->_v(2) = this->_v(attr_name[2] - 'x'); - vec->_v(3) = this->_v(attr_name[3] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase4), true, false); + } case 4: { + FLOATNAME(LVecBase4) *vec = new FLOATNAME(LVecBase4); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + vec->_v(3) = _this->_v(attr_name[3] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase4), true, false); + } } return NULL; @@ -112,8 +114,8 @@ __getattr__, const string &attr_name) { // Access: Published // Description: This is used to implement write masks. //////////////////////////////////////////////////////////////////// -int EXT_METHOD_ARGS(FLOATNAME(LVecBase2), -__setattr__, PyObject *self, const string &attr_name, PyObject *assign) { +INLINE_LINMATH int Extension:: +__setattr__(PyObject *self, const string &attr_name, PyObject *assign) { #ifndef NDEBUG // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { @@ -156,7 +158,7 @@ __setattr__, PyObject *self, const string &attr_name, PyObject *assign) { double value = PyFloat_AS_DOUBLE(fl); Py_DECREF(fl); - this->_v(attr_name[i] - 'x') = value; + _this->_v(attr_name[i] - 'x') = value; } Py_DECREF(fast); @@ -181,7 +183,7 @@ __setattr__, PyObject *self, const string &attr_name, PyObject *assign) { // Loop through the components in the attribute name, // and assign the floating-point value to every one of them. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { - this->_v((*it) - 'x') = value; + _this->_v((*it) - 'x') = value; } } diff --git a/panda/src/linmath/lvecBase2_ext_src.h b/panda/src/linmath/lvecBase2_ext_src.h new file mode 100644 index 0000000000..ecd459c119 --- /dev/null +++ b/panda/src/linmath/lvecBase2_ext_src.h @@ -0,0 +1,32 @@ +// Filename: lvecBase2_ext_src.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LVecBase2, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__reduce__(PyObject *self) const; + INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; + INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); + INLINE_LINMATH void __setitem__(int i, FLOATTYPE v); + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +#include "lvecBase2_ext_src.I" diff --git a/panda/src/linmath/lvecBase2_src.h b/panda/src/linmath/lvecBase2_src.h index e98ee8510e..f2daaae505 100644 --- a/panda/src/linmath/lvecBase2_src.h +++ b/panda/src/linmath/lvecBase2_src.h @@ -37,9 +37,9 @@ PUBLISHED: INLINE_LINMATH ~FLOATNAME(LVecBase2)(); - EXTENSION(PyObject *__reduce__(PyObject *self) const); - EXTENSION(PyObject *__getattr__(const string &attr_name) const); - EXTENSION(int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); + EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const); + EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); + EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); INLINE_LINMATH FLOATTYPE operator [](int i) const; INLINE_LINMATH FLOATTYPE &operator [](int i); diff --git a/panda/src/linmath/lvecBase3_ext.I b/panda/src/linmath/lvecBase3_ext.h similarity index 75% rename from panda/src/linmath/lvecBase3_ext.I rename to panda/src/linmath/lvecBase3_ext.h index 9733e67ef7..f68fd8d782 100644 --- a/panda/src/linmath/lvecBase3_ext.I +++ b/panda/src/linmath/lvecBase3_ext.h @@ -1,5 +1,5 @@ // Filename: lvecBase3_ext.I -// Created by: rdb (02Jan11) +// Created by: rdb (13Sep13) // //////////////////////////////////////////////////////////////////// // @@ -12,11 +12,16 @@ // //////////////////////////////////////////////////////////////////// +#ifndef LVECBASE3_EXT_H +#define LVECBASE3_EXT_H + #include "lvecBase3.h" +#include "extension.h" #include "fltnames.h" -#include "lvecBase3_ext_src.I" +#include "lvecBase3_ext_src.h" #include "dblnames.h" -#include "lvecBase3_ext_src.I" +#include "lvecBase3_ext_src.h" +#endif diff --git a/panda/src/linmath/lvecBase3_ext_src.I b/panda/src/linmath/lvecBase3_ext_src.I index 9992d3e456..9dc8fd4dab 100644 --- a/panda/src/linmath/lvecBase3_ext_src.I +++ b/panda/src/linmath/lvecBase3_ext_src.I @@ -24,10 +24,10 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_METHOD_ARGS(FLOATNAME(LVecBase3), -__setitem__, int i, FLOATTYPE v) { +INLINE_LINMATH void Extension:: +__setitem__(int i, FLOATTYPE v) { nassertv(i >= 0 && i < 3); - this->_v(i) = v; + _this->_v(i) = v; } //////////////////////////////////////////////////////////////////// @@ -35,12 +35,12 @@ __setitem__, int i, FLOATTYPE v) { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_CONST_METHOD_ARGS(FLOATNAME(LVecBase3), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_v(0)) << ", " - << MAYBE_ZERO(this->_v(1)) << ", " - << MAYBE_ZERO(this->_v(2)) << ")"; + << MAYBE_ZERO(_this->_v(0)) << ", " + << MAYBE_ZERO(_this->_v(1)) << ", " + << MAYBE_ZERO(_this->_v(2)) << ")"; } //////////////////////////////////////////////////////////////////// @@ -49,8 +49,8 @@ python_repr, ostream &out, const string &class_name) { // Description: This special Python method is implement to provide // support for the pickle module. //////////////////////////////////////////////////////////////////// -INLINE PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LVecBase3), -__reduce__, PyObject *self) { +INLINE_LINMATH PyObject *Extension:: +__reduce__(PyObject *self) const { // We should return at least a 2-tuple, (Class, (args)): the // necessary class object whose constructor we should call // (e.g. this), and the arguments necessary to reconstruct this @@ -61,7 +61,7 @@ __reduce__, PyObject *self) { } PyObject *result = Py_BuildValue("(O(fff))", this_class, - (*this)[0], (*this)[1], (*this)[2]); + (*_this)[0], (*_this)[1], (*_this)[2]); Py_DECREF(this_class); return result; } @@ -71,8 +71,8 @@ __reduce__, PyObject *self) { // Access: Published // Description: This is used to implement swizzle masks. //////////////////////////////////////////////////////////////////// -PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LVecBase3), -__getattr__, const string &attr_name) { +INLINE_LINMATH PyObject *Extension:: +__getattr__(const string &attr_name) const { // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { if (*it < 'x' || *it > 'z') { @@ -80,29 +80,31 @@ __getattr__, const string &attr_name) { } } - if (attr_name.size() == 1) { - return PyFloat_FromDouble(this->_v(attr_name[0] - 'x')); + switch (attr_name.size()) { + case 1: + return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); - } else if (attr_name.size() == 2) { - FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase2), true, false); + case 2: { + FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase2), true, false); - } else if (attr_name.size() == 3) { - FLOATNAME(LVecBase3) *vec = new FLOATNAME(LVecBase3); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - vec->_v(2) = this->_v(attr_name[2] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase3), true, false); + } case 3: { + FLOATNAME(LVecBase3) *vec = new FLOATNAME(LVecBase3); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase3), true, false); - } else if (attr_name.size() == 4) { - FLOATNAME(LVecBase4) *vec = new FLOATNAME(LVecBase4); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - vec->_v(2) = this->_v(attr_name[2] - 'x'); - vec->_v(3) = this->_v(attr_name[3] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase4), true, false); + } case 4: { + FLOATNAME(LVecBase4) *vec = new FLOATNAME(LVecBase4); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + vec->_v(3) = _this->_v(attr_name[3] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase4), true, false); + } } return NULL; @@ -113,8 +115,8 @@ __getattr__, const string &attr_name) { // Access: Published // Description: This is used to implement write masks. //////////////////////////////////////////////////////////////////// -int EXT_METHOD_ARGS(FLOATNAME(LVecBase3), -__setattr__, PyObject *self, const string &attr_name, PyObject *assign) { +INLINE_LINMATH int Extension:: +__setattr__(PyObject *self, const string &attr_name, PyObject *assign) { #ifndef NDEBUG // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { @@ -157,7 +159,7 @@ __setattr__, PyObject *self, const string &attr_name, PyObject *assign) { double value = PyFloat_AS_DOUBLE(fl); Py_DECREF(fl); - this->_v(attr_name[i] - 'x') = value; + _this->_v(attr_name[i] - 'x') = value; } Py_DECREF(fast); @@ -182,7 +184,7 @@ __setattr__, PyObject *self, const string &attr_name, PyObject *assign) { // Loop through the components in the attribute name, // and assign the floating-point value to every one of them. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { - this->_v((*it) - 'x') = value; + _this->_v((*it) - 'x') = value; } } diff --git a/panda/src/linmath/lvecBase3_ext_src.h b/panda/src/linmath/lvecBase3_ext_src.h new file mode 100644 index 0000000000..ecf3667303 --- /dev/null +++ b/panda/src/linmath/lvecBase3_ext_src.h @@ -0,0 +1,32 @@ +// Filename: lvecBase3_ext_src.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LVecBase3, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__reduce__(PyObject *self) const; + INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; + INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); + INLINE_LINMATH void __setitem__(int i, FLOATTYPE v); + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +#include "lvecBase3_ext_src.I" diff --git a/panda/src/linmath/lvecBase3_src.h b/panda/src/linmath/lvecBase3_src.h index c152a33857..c3635ea73c 100644 --- a/panda/src/linmath/lvecBase3_src.h +++ b/panda/src/linmath/lvecBase3_src.h @@ -38,9 +38,9 @@ PUBLISHED: INLINE_LINMATH ~FLOATNAME(LVecBase3)(); - EXTENSION(PyObject *__reduce__(PyObject *self) const); - EXTENSION(PyObject *__getattr__(const string &attr_name) const); - EXTENSION(int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); + EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const); + EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); + EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); INLINE_LINMATH FLOATTYPE operator [](int i) const; INLINE_LINMATH FLOATTYPE &operator [](int i); diff --git a/panda/src/linmath/lvecBase4_ext.I b/panda/src/linmath/lvecBase4_ext.h similarity index 75% rename from panda/src/linmath/lvecBase4_ext.I rename to panda/src/linmath/lvecBase4_ext.h index 9c045c7ff9..1cccf511e6 100644 --- a/panda/src/linmath/lvecBase4_ext.I +++ b/panda/src/linmath/lvecBase4_ext.h @@ -1,5 +1,5 @@ // Filename: lvecBase4_ext.I -// Created by: rdb (02Jan11) +// Created by: rdb (13Sep13) // //////////////////////////////////////////////////////////////////// // @@ -12,11 +12,16 @@ // //////////////////////////////////////////////////////////////////// +#ifndef LVECBASE4_EXT_H +#define LVECBASE4_EXT_H + #include "lvecBase4.h" +#include "extension.h" #include "fltnames.h" -#include "lvecBase4_ext_src.I" +#include "lvecBase4_ext_src.h" #include "dblnames.h" -#include "lvecBase4_ext_src.I" +#include "lvecBase4_ext_src.h" +#endif diff --git a/panda/src/linmath/lvecBase4_ext_src.I b/panda/src/linmath/lvecBase4_ext_src.I index 8d43b95936..c76a00e1ac 100644 --- a/panda/src/linmath/lvecBase4_ext_src.I +++ b/panda/src/linmath/lvecBase4_ext_src.I @@ -24,10 +24,10 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_METHOD_ARGS(FLOATNAME(LVecBase4), -__setitem__, int i, FLOATTYPE v) { +INLINE_LINMATH void Extension:: +__setitem__(int i, FLOATTYPE v) { nassertv(i >= 0 && i < 4); - this->_v(i) = v; + _this->_v(i) = v; } //////////////////////////////////////////////////////////////////// @@ -35,13 +35,13 @@ __setitem__, int i, FLOATTYPE v) { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_CONST_METHOD_ARGS(FLOATNAME(LVecBase4), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_v(0)) << ", " - << MAYBE_ZERO(this->_v(1)) << ", " - << MAYBE_ZERO(this->_v(2)) << ", " - << MAYBE_ZERO(this->_v(3)) << ")"; + << MAYBE_ZERO(_this->_v(0)) << ", " + << MAYBE_ZERO(_this->_v(1)) << ", " + << MAYBE_ZERO(_this->_v(2)) << ", " + << MAYBE_ZERO(_this->_v(3)) << ")"; } //////////////////////////////////////////////////////////////////// @@ -50,8 +50,8 @@ python_repr, ostream &out, const string &class_name) { // Description: This special Python method is implement to provide // support for the pickle module. //////////////////////////////////////////////////////////////////// -INLINE PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LVecBase4), -__reduce__, PyObject *self) { +INLINE_LINMATH PyObject *Extension:: +__reduce__(PyObject *self) const { // We should return at least a 2-tuple, (Class, (args)): the // necessary class object whose constructor we should call // (e.g. this), and the arguments necessary to reconstruct this @@ -62,7 +62,7 @@ __reduce__, PyObject *self) { } PyObject *result = Py_BuildValue("(O(ffff))", this_class, - (*this)[0], (*this)[1], (*this)[2], (*this)[3]); + (*_this)[0], (*_this)[1], (*_this)[2], (*_this)[3]); Py_DECREF(this_class); return result; } @@ -72,8 +72,8 @@ __reduce__, PyObject *self) { // Access: Published // Description: This is used to implement swizzle masks. //////////////////////////////////////////////////////////////////// -PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LVecBase4), -__getattr__, const string &attr_name) { +INLINE_LINMATH PyObject *Extension:: +__getattr__(const string &attr_name) const { // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { if (*it < 'w' || *it > 'z') { @@ -81,33 +81,35 @@ __getattr__, const string &attr_name) { } } - if (attr_name.size() == 1) { - if (attr_name[0] == 'w') { - return PyFloat_FromDouble(this->_v(3)); - } else { - return PyFloat_FromDouble(this->_v(attr_name[0] - 'x')); + switch (attr_name.size()) { + case 1: + if (attr_name[0] == 'w') { + return PyFloat_FromDouble(_this->_v(3)); + } else { + return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + } + + case 2: { + FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2); + vec->_v(0) = _this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); + vec->_v(1) = _this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase2), true, false); + + } case 3: { + FLOATNAME(LVecBase3) *vec = new FLOATNAME(LVecBase3); + vec->_v(0) = _this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); + vec->_v(1) = _this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); + vec->_v(2) = _this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase3), true, false); + + } case 4: { + FLOATNAME(LVecBase4) *vec = new FLOATNAME(LVecBase4); + vec->_v(0) = _this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); + vec->_v(1) = _this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); + vec->_v(2) = _this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); + vec->_v(3) = _this->_v((attr_name[3] == 'w') ? 3 : attr_name[3] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase4), true, false); } - - } else if (attr_name.size() == 2) { - FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2); - vec->_v(0) = this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); - vec->_v(1) = this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase2), true, false); - - } else if (attr_name.size() == 3) { - FLOATNAME(LVecBase3) *vec = new FLOATNAME(LVecBase3); - vec->_v(0) = this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); - vec->_v(1) = this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); - vec->_v(2) = this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase3), true, false); - - } else if (attr_name.size() == 4) { - FLOATNAME(LVecBase4) *vec = new FLOATNAME(LVecBase4); - vec->_v(0) = this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); - vec->_v(1) = this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); - vec->_v(2) = this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); - vec->_v(3) = this->_v((attr_name[3] == 'w') ? 3 : attr_name[3] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVecBase4), true, false); } return NULL; @@ -118,8 +120,8 @@ __getattr__, const string &attr_name) { // Access: Published // Description: This is used to implement write masks. //////////////////////////////////////////////////////////////////// -int EXT_METHOD_ARGS(FLOATNAME(LVecBase4), -__setattr__, PyObject *self, const string &attr_name, PyObject *assign) { +INLINE_LINMATH int Extension:: +__setattr__(PyObject *self, const string &attr_name, PyObject *assign) { #ifndef NDEBUG // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { @@ -162,7 +164,7 @@ __setattr__, PyObject *self, const string &attr_name, PyObject *assign) { double value = PyFloat_AS_DOUBLE(fl); Py_DECREF(fl); - this->_v((attr_name[i] == 'w') ? 3 : attr_name[i] - 'x') = value; + _this->_v((attr_name[i] == 'w') ? 3 : attr_name[i] - 'x') = value; } Py_DECREF(fast); @@ -187,21 +189,20 @@ __setattr__, PyObject *self, const string &attr_name, PyObject *assign) { // Loop through the components in the attribute name, // and assign the floating-point value to every one of them. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { - this->_v(((*it) == 'w') ? 3 : (*it) - 'x') = value; + _this->_v(((*it) == 'w') ? 3 : (*it) - 'x') = value; } } return 0; } - //////////////////////////////////////////////////////////////////// // Function: UnalignedLVecBase4::__setitem__ // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_METHOD_ARGS(FLOATNAME(UnalignedLVecBase4), -__setitem__, int i, FLOATTYPE v) { +INLINE_LINMATH void Extension:: +__setitem__(int i, FLOATTYPE v) { nassertv(i >= 0 && i < 4); - this->_v(i) = v; + _this->_v(i) = v; } diff --git a/panda/src/linmath/lvecBase4_ext_src.h b/panda/src/linmath/lvecBase4_ext_src.h new file mode 100644 index 0000000000..0d4306e256 --- /dev/null +++ b/panda/src/linmath/lvecBase4_ext_src.h @@ -0,0 +1,44 @@ +// Filename: lvecBase4_ext_src.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LVecBase4, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__reduce__(PyObject *self) const; + INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; + INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); + INLINE_LINMATH void __setitem__(int i, FLOATTYPE v); + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// UnalignedLVecBase4, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH void __setitem__(int i, FLOATTYPE v); +}; + +#include "lvecBase4_ext_src.I" diff --git a/panda/src/linmath/lvecBase4_src.h b/panda/src/linmath/lvecBase4_src.h index a27bace6ae..312c31a222 100644 --- a/panda/src/linmath/lvecBase4_src.h +++ b/panda/src/linmath/lvecBase4_src.h @@ -44,9 +44,9 @@ PUBLISHED: INLINE_LINMATH ~FLOATNAME(LVecBase4)(); - EXTENSION(PyObject *__reduce__(PyObject *self) const); - EXTENSION(PyObject *__getattr__(const string &attr_name) const); - EXTENSION(int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); + EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const); + EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); + EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); INLINE_LINMATH FLOATTYPE operator [](int i) const; INLINE_LINMATH FLOATTYPE &operator [](int i); diff --git a/panda/src/linmath/lvector2_ext.I b/panda/src/linmath/lvector2_ext.h similarity index 72% rename from panda/src/linmath/lvector2_ext.I rename to panda/src/linmath/lvector2_ext.h index 8b49ab6fd8..08ca44d07a 100644 --- a/panda/src/linmath/lvector2_ext.I +++ b/panda/src/linmath/lvector2_ext.h @@ -1,5 +1,5 @@ // Filename: lvector2_ext.I -// Created by: rdb (02Jan11) +// Created by: rdb (13Sep13) // //////////////////////////////////////////////////////////////////// // @@ -12,11 +12,18 @@ // //////////////////////////////////////////////////////////////////// +#ifndef LVECTOR2_EXT_H +#define LVECTOR2_EXT_H + #include "lvector2.h" +#include "extension.h" + +#include "lvecBase2_ext.h" #include "fltnames.h" -#include "lvector2_ext_src.I" +#include "lvector2_ext_src.h" #include "dblnames.h" -#include "lvector2_ext_src.I" +#include "lvector2_ext_src.h" +#endif diff --git a/panda/src/linmath/lvector2_ext_src.I b/panda/src/linmath/lvector2_ext_src.I index a355781b91..39fb074fce 100644 --- a/panda/src/linmath/lvector2_ext_src.I +++ b/panda/src/linmath/lvector2_ext_src.I @@ -12,7 +12,6 @@ // //////////////////////////////////////////////////////////////////// - #ifndef CPPPARSER IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector2); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector3); @@ -24,11 +23,11 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector4); // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_CONST_METHOD_ARGS(FLOATNAME(LVector2), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_v(0)) << ", " - << MAYBE_ZERO(this->_v(1)) << ")"; + << MAYBE_ZERO(_this->_v(0)) << ", " + << MAYBE_ZERO(_this->_v(1)) << ")"; } //////////////////////////////////////////////////////////////////// @@ -36,8 +35,8 @@ python_repr, ostream &out, const string &class_name) { // Access: Published // Description: This is used to implement swizzle masks. //////////////////////////////////////////////////////////////////// -INLINE PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LVector2), -__getattr__, const string &attr_name) { +INLINE_LINMATH PyObject *Extension:: +__getattr__(const string &attr_name) const { // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { if (*it != 'x' && *it != 'y') { @@ -45,42 +44,43 @@ __getattr__, const string &attr_name) { } } - if (attr_name.size() == 1) { - return PyFloat_FromDouble(this->_v(attr_name[0] - 'x')); + switch (attr_name.size()) { + case 1: + return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); - } else if (attr_name.size() == 2) { - FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector2), true, false); + case 2: { + FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector2), true, false); - } else if (attr_name.size() == 3) { - FLOATNAME(LVector3) *vec = new FLOATNAME(LVector3); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - vec->_v(2) = this->_v(attr_name[2] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector3), true, false); + } case 3: { + FLOATNAME(LVector3) *vec = new FLOATNAME(LVector3); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector3), true, false); - } else if (attr_name.size() == 4) { - FLOATNAME(LVector4) *vec = new FLOATNAME(LVector4); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - vec->_v(2) = this->_v(attr_name[2] - 'x'); - vec->_v(3) = this->_v(attr_name[3] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector4), true, false); + } case 4: { + FLOATNAME(LVector4) *vec = new FLOATNAME(LVector4); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + vec->_v(3) = _this->_v(attr_name[3] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector4), true, false); + } } return NULL; } -int EXT_METHOD_ARGS(FLOATNAME(LVecBase2), __setattr__, PyObject*, const string&, PyObject*); - //////////////////////////////////////////////////////////////////// // Function: LVector2::__setattr__ // Access: Published // Description: This is used to implement write masks. //////////////////////////////////////////////////////////////////// -INLINE int EXT_METHOD_ARGS(FLOATNAME(LVector2), -__setattr__, PyObject *self, const string &attr_name, PyObject *assign) { - return CALL_EXT_METHOD(FLOATNAME(LVecBase2), __setattr__, this, self, attr_name, assign); +INLINE_LINMATH int Extension:: +__setattr__(PyObject *self, const string &attr_name, PyObject *assign) { + // Upcall to LVecBase2. + return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); } diff --git a/panda/src/linmath/lvector2_ext_src.h b/panda/src/linmath/lvector2_ext_src.h new file mode 100644 index 0000000000..5f2c7838e6 --- /dev/null +++ b/panda/src/linmath/lvector2_ext_src.h @@ -0,0 +1,30 @@ +// Filename: lvector2_ext_src.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LVector2, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; + INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +#include "lvector2_ext_src.I" diff --git a/panda/src/linmath/lvector2_src.h b/panda/src/linmath/lvector2_src.h index f5eda0838c..8a0459737a 100644 --- a/panda/src/linmath/lvector2_src.h +++ b/panda/src/linmath/lvector2_src.h @@ -25,8 +25,8 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector2)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVector2)(FLOATTYPE x, FLOATTYPE y); - EXTENSION(PyObject *__getattr__(const string &attr_name) const); - EXTENSION(int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); + EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); + EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); INLINE_LINMATH static const FLOATNAME(LVector2) &zero(); INLINE_LINMATH static const FLOATNAME(LVector2) &unit_x(); diff --git a/panda/src/linmath/lvector3_ext.I b/panda/src/linmath/lvector3_ext.h similarity index 72% rename from panda/src/linmath/lvector3_ext.I rename to panda/src/linmath/lvector3_ext.h index 2ca8f5927f..4deae20e6d 100644 --- a/panda/src/linmath/lvector3_ext.I +++ b/panda/src/linmath/lvector3_ext.h @@ -1,5 +1,5 @@ // Filename: lvector3_ext.I -// Created by: rdb (02Jan11) +// Created by: rdb (13Sep13) // //////////////////////////////////////////////////////////////////// // @@ -12,11 +12,18 @@ // //////////////////////////////////////////////////////////////////// +#ifndef LVECTOR3_EXT_H +#define LVECTOR3_EXT_H + #include "lvector3.h" +#include "extension.h" + +#include "lvecBase3_ext.h" #include "fltnames.h" -#include "lvector3_ext_src.I" +#include "lvector3_ext_src.h" #include "dblnames.h" -#include "lvector3_ext_src.I" +#include "lvector3_ext_src.h" +#endif diff --git a/panda/src/linmath/lvector3_ext_src.I b/panda/src/linmath/lvector3_ext_src.I index 91320bd7c6..9706adfea3 100644 --- a/panda/src/linmath/lvector3_ext_src.I +++ b/panda/src/linmath/lvector3_ext_src.I @@ -12,7 +12,6 @@ // //////////////////////////////////////////////////////////////////// - #ifndef CPPPARSER IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector2); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector3); @@ -24,12 +23,12 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector4); // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_CONST_METHOD_ARGS(FLOATNAME(LVector3), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_v(0)) << ", " - << MAYBE_ZERO(this->_v(1)) << ", " - << MAYBE_ZERO(this->_v(2)) << ")"; + << MAYBE_ZERO(_this->_v(0)) << ", " + << MAYBE_ZERO(_this->_v(1)) << ", " + << MAYBE_ZERO(_this->_v(2)) << ")"; } //////////////////////////////////////////////////////////////////// @@ -37,8 +36,8 @@ python_repr, ostream &out, const string &class_name) { // Access: Published // Description: This is used to implement swizzle masks. //////////////////////////////////////////////////////////////////// -INLINE PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LVector3), -__getattr__, const string &attr_name) { +INLINE_LINMATH PyObject *Extension:: +__getattr__(const string &attr_name) const { // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { if (*it < 'x' || *it > 'z') { @@ -46,43 +45,43 @@ __getattr__, const string &attr_name) { } } - if (attr_name.size() == 1) { - return PyFloat_FromDouble(this->_v(attr_name[0] - 'x')); + switch (attr_name.size()) { + case 1: + return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); - } else if (attr_name.size() == 2) { - FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector2), true, false); + case 2: { + FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector2), true, false); - } else if (attr_name.size() == 3) { - FLOATNAME(LVector3) *vec = new FLOATNAME(LVector3); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - vec->_v(2) = this->_v(attr_name[2] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector3), true, false); + } case 3: { + FLOATNAME(LVector3) *vec = new FLOATNAME(LVector3); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector3), true, false); - } else if (attr_name.size() == 4) { - FLOATNAME(LVector4) *vec = new FLOATNAME(LVector4); - vec->_v(0) = this->_v(attr_name[0] - 'x'); - vec->_v(1) = this->_v(attr_name[1] - 'x'); - vec->_v(2) = this->_v(attr_name[2] - 'x'); - vec->_v(3) = this->_v(attr_name[3] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector4), true, false); + } case 4: { + FLOATNAME(LVector4) *vec = new FLOATNAME(LVector4); + vec->_v(0) = _this->_v(attr_name[0] - 'x'); + vec->_v(1) = _this->_v(attr_name[1] - 'x'); + vec->_v(2) = _this->_v(attr_name[2] - 'x'); + vec->_v(3) = _this->_v(attr_name[3] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector4), true, false); + } } return NULL; } -int EXT_METHOD_ARGS(FLOATNAME(LVecBase3), __setattr__, PyObject*, const string&, PyObject*); - //////////////////////////////////////////////////////////////////// // Function: LVector3::__setattr__ // Access: Published // Description: This is used to implement write masks. //////////////////////////////////////////////////////////////////// -INLINE int EXT_METHOD_ARGS(FLOATNAME(LVector3), -__setattr__, PyObject *self, const string &attr_name, PyObject *assign) { - return CALL_EXT_METHOD(FLOATNAME(LVecBase3), __setattr__, this, self, attr_name, assign); +INLINE_LINMATH int Extension:: +__setattr__(PyObject *self, const string &attr_name, PyObject *assign) { + // Upcall to LVecBase3. + return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); } - diff --git a/panda/src/linmath/lvector3_ext_src.h b/panda/src/linmath/lvector3_ext_src.h new file mode 100644 index 0000000000..85f6688d20 --- /dev/null +++ b/panda/src/linmath/lvector3_ext_src.h @@ -0,0 +1,30 @@ +// Filename: lvector3_ext_src.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LVector3, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; + INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +#include "lvector3_ext_src.I" diff --git a/panda/src/linmath/lvector3_src.h b/panda/src/linmath/lvector3_src.h index 65b3f099a3..282a41bcd5 100644 --- a/panda/src/linmath/lvector3_src.h +++ b/panda/src/linmath/lvector3_src.h @@ -31,8 +31,8 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector3)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVector3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z); - EXTENSION(PyObject *__getattr__(const string &attr_name) const); - EXTENSION(int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); + EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); + EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); INLINE_LINMATH static const FLOATNAME(LVector3) &zero(); INLINE_LINMATH static const FLOATNAME(LVector3) &unit_x(); diff --git a/panda/src/linmath/lvector4_ext.I b/panda/src/linmath/lvector4_ext.h similarity index 72% rename from panda/src/linmath/lvector4_ext.I rename to panda/src/linmath/lvector4_ext.h index cf59c76fde..8bd174885e 100644 --- a/panda/src/linmath/lvector4_ext.I +++ b/panda/src/linmath/lvector4_ext.h @@ -1,5 +1,5 @@ // Filename: lvector4_ext.I -// Created by: rdb (02Jan11) +// Created by: rdb (13Sep13) // //////////////////////////////////////////////////////////////////// // @@ -12,11 +12,18 @@ // //////////////////////////////////////////////////////////////////// +#ifndef LVECTOR4_EXT_H +#define LVECTOR4_EXT_H + #include "lvector4.h" +#include "extension.h" + +#include "lvecBase4_ext.h" #include "fltnames.h" -#include "lvector4_ext_src.I" +#include "lvector4_ext_src.h" #include "dblnames.h" -#include "lvector4_ext_src.I" +#include "lvector4_ext_src.h" +#endif diff --git a/panda/src/linmath/lvector4_ext_src.I b/panda/src/linmath/lvector4_ext_src.I index b6b7f58d35..a9ae9eb8d0 100644 --- a/panda/src/linmath/lvector4_ext_src.I +++ b/panda/src/linmath/lvector4_ext_src.I @@ -12,7 +12,6 @@ // //////////////////////////////////////////////////////////////////// - #ifndef CPPPARSER IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector2); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector3); @@ -24,13 +23,13 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector4); // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE void EXT_CONST_METHOD_ARGS(FLOATNAME(LVector4), -python_repr, ostream &out, const string &class_name) { +INLINE_LINMATH void Extension:: +python_repr(ostream &out, const string &class_name) const { out << class_name << "(" - << MAYBE_ZERO(this->_v(0)) << ", " - << MAYBE_ZERO(this->_v(1)) << ", " - << MAYBE_ZERO(this->_v(2)) << ", " - << MAYBE_ZERO(this->_v(3)) << ")"; + << MAYBE_ZERO(_this->_v(0)) << ", " + << MAYBE_ZERO(_this->_v(1)) << ", " + << MAYBE_ZERO(_this->_v(2)) << ", " + << MAYBE_ZERO(_this->_v(3)) << ")"; } //////////////////////////////////////////////////////////////////// @@ -38,8 +37,8 @@ python_repr, ostream &out, const string &class_name) { // Access: Published // Description: This is used to implement swizzle masks. //////////////////////////////////////////////////////////////////// -INLINE PyObject *EXT_CONST_METHOD_ARGS(FLOATNAME(LVector4), -__getattr__, const string &attr_name) { +INLINE_LINMATH PyObject *Extension:: +__getattr__(const string &attr_name) const { // Validate the attribute name. for (string::const_iterator it = attr_name.begin(); it < attr_name.end(); it++) { if (*it < 'w' || *it > 'z') { @@ -47,47 +46,47 @@ __getattr__, const string &attr_name) { } } - if (attr_name.size() == 1) { - if (attr_name[0] == 'w') { - return PyFloat_FromDouble(this->_v(3)); - } else { - return PyFloat_FromDouble(this->_v(attr_name[0] - 'x')); + switch (attr_name.size()) { + case 1: + if (attr_name[0] == 'w') { + return PyFloat_FromDouble(_this->_v(3)); + } else { + return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + } + + case 2: { + FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2); + vec->_v(0) = _this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); + vec->_v(1) = _this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector2), true, false); + + } case 3: { + FLOATNAME(LVector3) *vec = new FLOATNAME(LVector3); + vec->_v(0) = _this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); + vec->_v(1) = _this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); + vec->_v(2) = _this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector3), true, false); + + } case 4: { + FLOATNAME(LVector4) *vec = new FLOATNAME(LVector4); + vec->_v(0) = _this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); + vec->_v(1) = _this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); + vec->_v(2) = _this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); + vec->_v(3) = _this->_v((attr_name[3] == 'w') ? 3 : attr_name[3] - 'x'); + return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector4), true, false); } - - } else if (attr_name.size() == 2) { - FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2); - vec->_v(0) = this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); - vec->_v(1) = this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector2), true, false); - - } else if (attr_name.size() == 3) { - FLOATNAME(LVector3) *vec = new FLOATNAME(LVector3); - vec->_v(0) = this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); - vec->_v(1) = this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); - vec->_v(2) = this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector3), true, false); - - } else if (attr_name.size() == 4) { - FLOATNAME(LVector4) *vec = new FLOATNAME(LVector4); - vec->_v(0) = this->_v((attr_name[0] == 'w') ? 3 : attr_name[0] - 'x'); - vec->_v(1) = this->_v((attr_name[1] == 'w') ? 3 : attr_name[1] - 'x'); - vec->_v(2) = this->_v((attr_name[2] == 'w') ? 3 : attr_name[2] - 'x'); - vec->_v(3) = this->_v((attr_name[3] == 'w') ? 3 : attr_name[3] - 'x'); - return DTool_CreatePyInstance((void *)vec, FLOATNAME(Dtool_LVector4), true, false); } return NULL; } -int EXT_METHOD_ARGS(FLOATNAME(LVecBase4), __setattr__, PyObject*, const string&, PyObject*); - //////////////////////////////////////////////////////////////////// // Function: LVector4::__setattr__ // Access: Published // Description: This is used to implement write masks. //////////////////////////////////////////////////////////////////// -INLINE int EXT_METHOD_ARGS(FLOATNAME(LVector4), -__setattr__, PyObject *self, const string &attr_name, PyObject *assign) { - return CALL_EXT_METHOD(FLOATNAME(LVecBase4), __setattr__, this, self, attr_name, assign); +INLINE_LINMATH int Extension:: +__setattr__(PyObject *self, const string &attr_name, PyObject *assign) { + // Upcall to LVecBase4. + return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); } - diff --git a/panda/src/linmath/lvector4_ext_src.h b/panda/src/linmath/lvector4_ext_src.h new file mode 100644 index 0000000000..e6e708f36b --- /dev/null +++ b/panda/src/linmath/lvector4_ext_src.h @@ -0,0 +1,30 @@ +// Filename: lvector4_ext_src.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// LVector4, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; + INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); + INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; +}; + +#include "lvector4_ext_src.I" diff --git a/panda/src/linmath/lvector4_src.h b/panda/src/linmath/lvector4_src.h index d5b69e508a..d9c639fcf1 100644 --- a/panda/src/linmath/lvector4_src.h +++ b/panda/src/linmath/lvector4_src.h @@ -25,8 +25,8 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector4)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVector4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w); - EXTENSION(PyObject *__getattr__(const string &attr_name) const); - EXTENSION(int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); + EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); + EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); INLINE_LINMATH static const FLOATNAME(LVector4) &zero(); INLINE_LINMATH static const FLOATNAME(LVector4) &unit_x(); diff --git a/panda/src/rocket/rocketRegion_ext.I b/panda/src/rocket/rocketRegion_ext.cxx similarity index 90% rename from panda/src/rocket/rocketRegion_ext.I rename to panda/src/rocket/rocketRegion_ext.cxx index d3f29b5ec5..33462dd628 100644 --- a/panda/src/rocket/rocketRegion_ext.I +++ b/panda/src/rocket/rocketRegion_ext.cxx @@ -1,4 +1,4 @@ -// Filename: rocketRegion_ext.I +// Filename: rocketRegion_ext.cxx // Created by: rdb (06Dec11) // //////////////////////////////////////////////////////////////////// @@ -13,9 +13,9 @@ //////////////////////////////////////////////////////////////////// #include "rocketRegion.h" +#include "extension.h" #ifndef CPPPARSER -#undef this #define HAVE_LONG_LONG 1 #include #include @@ -31,10 +31,10 @@ // It's best to call this method just once and store // the context in a Python variable, to avoid overhead. //////////////////////////////////////////////////////////////////// -PyObject* EXT_CONST_METHOD(RocketRegion, -get_context) { +PyObject* Extension:: +get_context() const { try { - Rocket::Core::Context* context = _ext_this->get_context(); + Rocket::Core::Context* context = _this->get_context(); python::object py_context = Rocket::Core::Python::Utilities::MakeObject(context); // Make sure the context won't be destroyed before both the Python diff --git a/panda/src/rocket/rocketRegion_ext.h b/panda/src/rocket/rocketRegion_ext.h new file mode 100644 index 0000000000..8323761b88 --- /dev/null +++ b/panda/src/rocket/rocketRegion_ext.h @@ -0,0 +1,39 @@ +// Filename: rocketRegion_ext.h +// Created by: rdb (13Sep13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef ROCKETREGION_EXT_H +#define ROCKETREGION_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "geomVertexArrayData.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// GeomVertexArrayData, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: +}; + +#endif // HAVE_PYTHON + +#endif // ROCKETREGION_EXT_H