From 57e5c8fb2544b3f7fa5efda4eea3bbbfdd939d69 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 10 Sep 2015 15:29:31 +0200 Subject: [PATCH] Wrap TypeHandle and ButtonHandle as ints in C wrappers --- dtool/src/dtoolbase/typeHandle.I | 15 ++++ dtool/src/dtoolbase/typeHandle.h | 5 +- dtool/src/interrogate/functionRemap.cxx | 48 ++++++++---- dtool/src/interrogate/interfaceMakerC.cxx | 27 +++++++ dtool/src/interrogate/interfaceMakerC.h | 2 + .../interrogate/interrogate_composite2.cxx | 1 + .../interrogate/parameterRemapHandleToInt.cxx | 65 ++++++++++++++++ .../interrogate/parameterRemapHandleToInt.h | 40 ++++++++++ dtool/src/interrogate/parameterRemapThis.cxx | 4 +- dtool/src/interrogate/typeManager.cxx | 27 ++++++- dtool/src/interrogate/typeManager.h | 1 + panda/src/express/config_express.N | 2 +- panda/src/linmath/luse.N | 74 +++++++++---------- panda/src/putil/buttonHandle.h | 2 +- panda/src/putil/config_util.N | 2 +- 15 files changed, 257 insertions(+), 58 deletions(-) create mode 100644 dtool/src/interrogate/parameterRemapHandleToInt.cxx create mode 100644 dtool/src/interrogate/parameterRemapHandleToInt.h diff --git a/dtool/src/dtoolbase/typeHandle.I b/dtool/src/dtoolbase/typeHandle.I index 867bdb4cea..ceb46a8e41 100644 --- a/dtool/src/dtoolbase/typeHandle.I +++ b/dtool/src/dtoolbase/typeHandle.I @@ -263,3 +263,18 @@ INLINE TypeHandle:: operator bool () const { return (_index != 0); } + +//////////////////////////////////////////////////////////////////// +// Function: TypeHandle::from_index +// Access: Public, Static +// Description: Creates a TypeHandle from a type index without +// error checking, for use by internal functions. +// +// See TypeRegistry::find_type_by_id(). +//////////////////////////////////////////////////////////////////// +INLINE TypeHandle TypeHandle:: +from_index(int index) { + TypeHandle handle; + handle._index = index; + return handle; +} diff --git a/dtool/src/dtoolbase/typeHandle.h b/dtool/src/dtoolbase/typeHandle.h index f94e983447..c05e25dd46 100644 --- a/dtool/src/dtoolbase/typeHandle.h +++ b/dtool/src/dtoolbase/typeHandle.h @@ -82,7 +82,7 @@ class TypedObject; // ancestry of a particular type may be queried, and the // type name may be retrieved for run-time display. //////////////////////////////////////////////////////////////////// -class EXPCL_DTOOL TypeHandle { +class EXPCL_DTOOL TypeHandle FINAL { PUBLISHED: enum MemoryClass { MC_singleton, @@ -140,6 +140,9 @@ PUBLISHED: INLINE static TypeHandle none(); INLINE operator bool () const; +public: + INLINE static TypeHandle from_index(int index); + private: int _index; static TypeHandle _none; diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index 5e602a7553..2bf2fb06da 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -17,6 +17,7 @@ #include "interrogate.h" #include "parameterRemap.h" #include "parameterRemapThis.h" +#include "parameterRemapHandleToInt.h" #include "parameterRemapUnchanged.h" #include "interfaceMaker.h" #include "interrogateBuilder.h" @@ -146,8 +147,13 @@ call_function(ostream &out, int indent_level, bool convert_result, } else if (_type == T_typecast_method) { // A typecast method can be invoked implicitly. string cast_expr = - "(" + _return_type->get_orig_type()->get_local_name(&parser) + - ")(*" + container + ")"; + "(" + _return_type->get_orig_type()->get_local_name(&parser) + ")"; + + if (TypeManager::is_handle(_cpptype)) { + cast_expr += "(" + container + ")"; + } else { + cast_expr += "(*" + container + ")"; + } if (!convert_result) { return_expr = cast_expr; @@ -177,10 +183,7 @@ call_function(ostream &out, int indent_level, bool convert_result, } else if (_type == T_constructor) { // A special case for constructors. - string defconstruct = builder.in_defconstruct(_cpptype->get_local_name(&parser)); - if (pexprs.empty() && !defconstruct.empty()) { - return_expr = defconstruct; - } else if (_extension) { + if (_extension) { // Extension constructors are a special case. We assume there is a // default constructor for the class, and the actual construction is // done by an __init__ method. @@ -192,8 +195,22 @@ call_function(ostream &out, int indent_level, bool convert_result, << get_call_str("result", pexprs) << ";\n"; return_expr = "result"; + } else { - return_expr = "new " + get_call_str(container, pexprs); + string defconstruct = builder.in_defconstruct(_cpptype->get_local_name(&parser)); + string call_expr; + + if (pexprs.empty() && !defconstruct.empty()) { + call_expr = defconstruct; + } else { + call_expr = get_call_str(container, pexprs); + } + + if (!_return_type->return_value_needs_management()) { + return_expr = _return_type->get_return_expr(call_expr); + } else { + return_expr = "new " + call_expr; + } } if (_void_return) { nout << "Error, constructor for " << *_cpptype << " returning void.\n"; @@ -448,12 +465,9 @@ get_call_str(const string &container, const vector_string &pexprs) const { } else if (_has_this && !container.empty()) { // If we have a "this" parameter, the calling convention is also // a bit different. - if (container == "local_this") { - // This isn't important, it just looks a bit prettier. - call << container << "->" << _cppfunc->get_local_name(); - } else { - call << "(" << container << ")->" << _cppfunc->get_local_name(); - } + call << "("; + _parameters[0]._remap->pass_parameter(call, container); + call << ")." << _cppfunc->get_local_name(); } else { call << _cppfunc->get_local_name(&parser); @@ -569,7 +583,13 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak Parameter param; param._name = "this"; param._has_name = true; - param._remap = new ParameterRemapThis(_cpptype, _const_method); + if (_const_method) { + CPPType *const_type = CPPType::new_type(new CPPConstType(_cpptype)); + param._remap = interface_maker->remap_parameter(_cpptype, const_type); + } else { + param._remap = interface_maker->remap_parameter(_cpptype, _cpptype); + } + // param._remap = new ParameterRemapThis(_cpptype, _const_method); _parameters.push_back(param); _first_true_parameter = 1; } diff --git a/dtool/src/interrogate/interfaceMakerC.cxx b/dtool/src/interrogate/interfaceMakerC.cxx index 25eeb87023..9bd21a9922 100644 --- a/dtool/src/interrogate/interfaceMakerC.cxx +++ b/dtool/src/interrogate/interfaceMakerC.cxx @@ -16,6 +16,7 @@ #include "interrogateBuilder.h" #include "interrogate.h" #include "functionRemap.h" +#include "parameterRemapHandleToInt.h" #include "parameterRemapUnchanged.h" #include "typeManager.h" @@ -89,6 +90,32 @@ write_functions(ostream &out) { InterfaceMaker::write_functions(out); } +//////////////////////////////////////////////////////////////////// +// Function: InterfaceMakerC::remap_parameter +// Access: Public, Virtual +// Description: Allocates a new ParameterRemap object suitable to the +// indicated parameter type. If struct_type is +// non-NULL, it is the type of the enclosing class for +// the function (method) in question. +// +// The return value is a newly-allocated ParameterRemap +// object, if the parameter type is acceptable, or NULL +// if the parameter type cannot be handled. +//////////////////////////////////////////////////////////////////// +ParameterRemap *InterfaceMakerC:: +remap_parameter(CPPType *struct_type, CPPType *param_type) { + // Wrap TypeHandle and ButtonHandle, which are practically just + // ints, as an integer instead of a pointer. It makes things easier + // on the scripting language, especially if there has to be a + // dynamic downcasting system on the scripting language side. + if (TypeManager::is_handle(param_type)) { + return new ParameterRemapHandleToInt(param_type); + + } else { + return InterfaceMaker::remap_parameter(struct_type, param_type); + } +} + //////////////////////////////////////////////////////////////////// // Function: InterfaceMakerC::synthesize_this_parameter // Access: Public, Virtual diff --git a/dtool/src/interrogate/interfaceMakerC.h b/dtool/src/interrogate/interfaceMakerC.h index 3faea7bae8..ee715424ac 100644 --- a/dtool/src/interrogate/interfaceMakerC.h +++ b/dtool/src/interrogate/interfaceMakerC.h @@ -36,6 +36,8 @@ public: virtual void write_prototypes(ostream &out,ostream *out_h); virtual void write_functions(ostream &out); + virtual ParameterRemap *remap_parameter(CPPType *struct_type, CPPType *param_type); + virtual bool synthesize_this_parameter(); protected: diff --git a/dtool/src/interrogate/interrogate_composite2.cxx b/dtool/src/interrogate/interrogate_composite2.cxx index 39000d2778..a427cf2674 100644 --- a/dtool/src/interrogate/interrogate_composite2.cxx +++ b/dtool/src/interrogate/interrogate_composite2.cxx @@ -14,5 +14,6 @@ #include "parameterRemapReferenceToPointer.cxx" #include "parameterRemapThis.cxx" #include "parameterRemapToString.cxx" +#include "parameterRemapHandleToInt.cxx" #include "parameterRemapUnchanged.cxx" diff --git a/dtool/src/interrogate/parameterRemapHandleToInt.cxx b/dtool/src/interrogate/parameterRemapHandleToInt.cxx new file mode 100644 index 0000000000..82220c1b75 --- /dev/null +++ b/dtool/src/interrogate/parameterRemapHandleToInt.cxx @@ -0,0 +1,65 @@ +// Filename: parameterRemapHandleToInt.cxx +// Created by: rdb (08Sep15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "parameterRemapHandleToInt.h" +#include "interrogate.h" +#include "interrogateBuilder.h" +#include "typeManager.h" + +#include "cppType.h" +#include "cppDeclaration.h" +#include "cppConstType.h" +#include "cppPointerType.h" + +//////////////////////////////////////////////////////////////////// +// Function: ParameterRemapHandleToInt::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +ParameterRemapHandleToInt:: +ParameterRemapHandleToInt(CPPType *orig_type) : + ParameterRemap(orig_type) +{ + _new_type = TypeManager::get_int_type(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ParameterRemapHandleToInt::pass_parameter +// Access: Public, Virtual +// Description: Outputs an expression that converts the indicated +// variable from the new type to the original type, for +// passing into the actual C++ function. +//////////////////////////////////////////////////////////////////// +void ParameterRemapHandleToInt:: +pass_parameter(ostream &out, const string &variable_name) { + CPPType *unwrapped = TypeManager::unwrap_const(_orig_type); + + if (unwrapped->get_local_name(&parser) == "TypeHandle") { + out << "TypeHandle::from_index(" << variable_name << ")"; + } else { + out << unwrapped->get_local_name(&parser) << "(" << variable_name << ")"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ParameterRemapHandleToInt::get_return_expr +// Access: Public, Virtual +// Description: Returns an expression that evalutes to the +// appropriate value type for returning from the +// function, given an expression of the original type. +//////////////////////////////////////////////////////////////////// +string ParameterRemapHandleToInt:: +get_return_expr(const string &expression) { + return "(" + expression + ").get_index()"; +} diff --git a/dtool/src/interrogate/parameterRemapHandleToInt.h b/dtool/src/interrogate/parameterRemapHandleToInt.h new file mode 100644 index 0000000000..4a2915d279 --- /dev/null +++ b/dtool/src/interrogate/parameterRemapHandleToInt.h @@ -0,0 +1,40 @@ +// Filename: parameterRemapHandleToInt.h +// Created by: rdb (08Sep15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 PARAMETERREMAPHANDLETOINT_H +#define PARAMETERREMAPHANDLETOINT_H + +#include "dtoolbase.h" + +#include "parameterRemap.h" + +//////////////////////////////////////////////////////////////////// +// Class : ParameterRemapHandleToInt +// Description : A ParameterRemap class that handles remapping a +// Handle parameter to an integer. This makes it +// easier to set up a dynamic typing system on the +// scripting language side. +// +// It also applies to ButtonHandle or any other class +// with the same semantics, because why not. +//////////////////////////////////////////////////////////////////// +class ParameterRemapHandleToInt : public ParameterRemap { +public: + ParameterRemapHandleToInt(CPPType *orig_type); + + virtual void pass_parameter(ostream &out, const string &variable_name); + virtual string get_return_expr(const string &expression); +}; + +#endif diff --git a/dtool/src/interrogate/parameterRemapThis.cxx b/dtool/src/interrogate/parameterRemapThis.cxx index db6e1d6d30..220f01ab44 100644 --- a/dtool/src/interrogate/parameterRemapThis.cxx +++ b/dtool/src/interrogate/parameterRemapThis.cxx @@ -45,8 +45,8 @@ ParameterRemapThis(CPPType *type, bool is_const) : // passing into the actual C++ function. //////////////////////////////////////////////////////////////////// void ParameterRemapThis:: -pass_parameter(ostream &out, const string &) { - out << "**invalid**"; +pass_parameter(ostream &out, const string &variable_name) { + out << "(*" << variable_name << ")"; } //////////////////////////////////////////////////////////////////// diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index c8e6dce9c7..1fd968d09f 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -1820,6 +1820,31 @@ is_Py_buffer(CPPType *type) { } } +//////////////////////////////////////////////////////////////////// +// Function: TypeManager::is_handle +// Access: Public, Static +// Description: Returns true if the indicated type is TypeHandle +// or a class with identical semantics like ButtonHandle. +//////////////////////////////////////////////////////////////////// +bool TypeManager:: +is_handle(CPPType *type) { + switch (type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_handle(type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_extension: + case CPPDeclaration::ST_struct: + return (type->get_local_name(&parser) == "TypeHandle" || + type->get_local_name(&parser) == "ButtonHandle"); + + case CPPDeclaration::ST_typedef: + return is_handle(type->as_typedef_type()->_type); + + default: + return false; + } +} + //////////////////////////////////////////////////////////////////// // Function: TypeManager::is_ostream // Access: Public, Static @@ -2631,7 +2656,7 @@ is_trivial(CPPType *source_type) { return is_trivial(source_type->as_typedef_type()->_type); default: - if (source_type->is_trivial()) { + if (source_type->is_trivial() || is_handle(source_type)) { return true; } else { // This is a bit of a hack. is_trivial() returns false for types that diff --git a/dtool/src/interrogate/typeManager.h b/dtool/src/interrogate/typeManager.h index 29b29eb2c7..5df95c63b9 100644 --- a/dtool/src/interrogate/typeManager.h +++ b/dtool/src/interrogate/typeManager.h @@ -112,6 +112,7 @@ public: static bool is_PyUnicodeObject(CPPType *type); static bool is_pointer_to_Py_buffer(CPPType *type); static bool is_Py_buffer(CPPType *type); + static bool is_handle(CPPType *type); static bool involves_unpublished(CPPType *type); static bool involves_protected(CPPType *type); diff --git a/panda/src/express/config_express.N b/panda/src/express/config_express.N index ad6e244b4e..454c630ed2 100644 --- a/panda/src/express/config_express.N +++ b/panda/src/express/config_express.N @@ -1,4 +1,4 @@ -defconstruct TypeHandle new TypeHandle(TypeHandle::none()) +defconstruct TypeHandle TypeHandle(TypeHandle::none()) forcetype PandaSystem forcetype DSearchPath diff --git a/panda/src/linmath/luse.N b/panda/src/linmath/luse.N index 20da19f1c8..ce89055b3d 100644 --- a/panda/src/linmath/luse.N +++ b/panda/src/linmath/luse.N @@ -1,46 +1,46 @@ -defconstruct LPoint2f new LPoint2f(0.0f) -defconstruct LPoint3f new LPoint3f(0.0f) -defconstruct LPoint4f new LPoint4f(0.0f) -defconstruct LPoint2d new LPoint2d(0.0) -defconstruct LPoint3d new LPoint3d(0.0) -defconstruct LPoint4d new LPoint4d(0.0) -defconstruct LPoint2i new LPoint2i(0) -defconstruct LPoint3i new LPoint3i(0) -defconstruct LPoint4i new LPoint4i(0) +defconstruct LPoint2f LPoint2f(0.0f) +defconstruct LPoint3f LPoint3f(0.0f) +defconstruct LPoint4f LPoint4f(0.0f) +defconstruct LPoint2d LPoint2d(0.0) +defconstruct LPoint3d LPoint3d(0.0) +defconstruct LPoint4d LPoint4d(0.0) +defconstruct LPoint2i LPoint2i(0) +defconstruct LPoint3i LPoint3i(0) +defconstruct LPoint4i LPoint4i(0) -defconstruct LVecBase2f new LVecBase2f(0.0f) -defconstruct LVecBase3f new LVecBase3f(0.0f) -defconstruct LVecBase4f new LVecBase4f(0.0f) -defconstruct LVecBase2d new LVecBase2d(0.0) -defconstruct LVecBase3d new LVecBase3d(0.0) -defconstruct LVecBase4d new LVecBase4d(0.0) -defconstruct LVecBase2i new LVecBase2i(0) -defconstruct LVecBase3i new LVecBase3i(0) -defconstruct LVecBase4i new LVecBase4i(0) +defconstruct LVecBase2f LVecBase2f(0.0f) +defconstruct LVecBase3f LVecBase3f(0.0f) +defconstruct LVecBase4f LVecBase4f(0.0f) +defconstruct LVecBase2d LVecBase2d(0.0) +defconstruct LVecBase3d LVecBase3d(0.0) +defconstruct LVecBase4d LVecBase4d(0.0) +defconstruct LVecBase2i LVecBase2i(0) +defconstruct LVecBase3i LVecBase3i(0) +defconstruct LVecBase4i LVecBase4i(0) -defconstruct LVector2f new LVector2f(0.0f) -defconstruct LVector3f new LVector3f(0.0f) -defconstruct LVector4f new LVector4f(0.0f) -defconstruct LVector2d new LVector2d(0.0) -defconstruct LVector3d new LVector3d(0.0) -defconstruct LVector4d new LVector4d(0.0) -defconstruct LVector2i new LVector2i(0) -defconstruct LVector3i new LVector3i(0) -defconstruct LVector4i new LVector4i(0) +defconstruct LVector2f LVector2f(0.0f) +defconstruct LVector3f LVector3f(0.0f) +defconstruct LVector4f LVector4f(0.0f) +defconstruct LVector2d LVector2d(0.0) +defconstruct LVector3d LVector3d(0.0) +defconstruct LVector4d LVector4d(0.0) +defconstruct LVector2i LVector2i(0) +defconstruct LVector3i LVector3i(0) +defconstruct LVector4i LVector4i(0) -defconstruct LMatrix3f new LMatrix3f(LMatrix3f::ident_mat()) -defconstruct LMatrix4f new LMatrix4f(LMatrix4f::ident_mat()) -defconstruct LMatrix3d new LMatrix3d(LMatrix3d::ident_mat()) -defconstruct LMatrix4d new LMatrix4d(LMatrix4d::ident_mat()) +defconstruct LMatrix3f LMatrix3f(LMatrix3f::ident_mat()) +defconstruct LMatrix4f LMatrix4f(LMatrix4f::ident_mat()) +defconstruct LMatrix3d LMatrix3d(LMatrix3d::ident_mat()) +defconstruct LMatrix4d LMatrix4d(LMatrix4d::ident_mat()) -defconstruct LQuaternionf new LQuaternionf(LQuaternionf::ident_quat()) -defconstruct LRotationf new LRotationf(LQuaternionf::ident_quat()) -defconstruct LOrientationf new LOrientationf(LQuaternionf::ident_quat()) +defconstruct LQuaternionf LQuaternionf(LQuaternionf::ident_quat()) +defconstruct LRotationf LRotationf(LQuaternionf::ident_quat()) +defconstruct LOrientationf LOrientationf(LQuaternionf::ident_quat()) -defconstruct LQuaterniond new LQuaterniond(LQuaterniond::ident_quat()) -defconstruct LRotationd new LRotationd(LQuaterniond::ident_quat()) -defconstruct LOrientationd new LOrientationd(LQuaterniond::ident_quat()) +defconstruct LQuaterniond LQuaterniond(LQuaterniond::ident_quat()) +defconstruct LRotationd LRotationd(LQuaterniond::ident_quat()) +defconstruct LOrientationd LOrientationd(LQuaterniond::ident_quat()) # We don't want to accidentally include any of the _src files in the # generated output, since these files aren't intended to be included by diff --git a/panda/src/putil/buttonHandle.h b/panda/src/putil/buttonHandle.h index c53f9a6ac9..dcb0e82db3 100644 --- a/panda/src/putil/buttonHandle.h +++ b/panda/src/putil/buttonHandle.h @@ -25,7 +25,7 @@ // device, including keyboard buttons and mouse buttons // (but see KeyboardButton and MouseButton). //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA_PUTIL ButtonHandle { +class EXPCL_PANDA_PUTIL ButtonHandle FINAL { PUBLISHED: INLINE ButtonHandle(); INLINE ButtonHandle(int index); diff --git a/panda/src/putil/config_util.N b/panda/src/putil/config_util.N index 4bcc299b1e..3e7f11238a 100644 --- a/panda/src/putil/config_util.N +++ b/panda/src/putil/config_util.N @@ -1,4 +1,4 @@ -defconstruct ButtonHandle new ButtonHandle(0) +defconstruct ButtonHandle ButtonHandle(0) ignoremember _factory ignoremember get_factory