diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index be91171c50..f30edfd2e5 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -163,14 +163,12 @@ call_function(ostream &out, int indent_level, bool convert_result, if (pexprs.empty() && !defconstruct.empty()) { return_expr = defconstruct; } else if (_extension) { - // Extension constructors are a special case. We allocate memory, but - // the actual construction is done by an __init__ method, similar to how - // it works in Python. + // 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. InterfaceMaker::indent(out, indent_level); _return_type->get_new_type()->output_instance(out, "result", &parser); - out << " = (" << _cpptype->get_local_name(&parser) - << " *) " << _cpptype->get_local_name(&parser) - << "::operator new(sizeof(" << _cpptype->get_local_name(&parser) << "));\n"; + out << " = new " << _cpptype->get_local_name(&parser) << ";\n"; InterfaceMaker::indent(out, indent_level) << get_call_str("result", pexprs) << ";\n"; diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index f07093c740..b83bf5213c 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -3260,8 +3260,7 @@ if (not RUNTIME): TargetAdd('libp3gobj.in', opts=OPTS, input=IGATEFILES) TargetAdd('libp3gobj.in', opts=['IMOD:panda3d.core', 'ILIB:libp3gobj', 'SRCDIR:panda/src/gobj']) TargetAdd('libp3gobj_igate.obj', input='libp3gobj.in', opts=["DEPENDENCYONLY"]) - TargetAdd('p3gobj_geomVertexArrayData_ext.obj', opts=OPTS, input='geomVertexArrayData_ext.cxx') - TargetAdd('p3gobj_internalName_ext.obj', opts=OPTS, input='internalName_ext.cxx') + TargetAdd('p3gobj_ext_composite.obj', opts=OPTS, input='p3gobj_ext_composite.cxx') # # DIRECTORY: panda/src/pgraphnodes/ @@ -3725,8 +3724,7 @@ if (not RUNTIME): TargetAdd('core.pyd', input='p3putil_pythonCallbackObject.obj') TargetAdd('core.pyd', input='p3pnmimage_pfmFile_ext.obj') TargetAdd('core.pyd', input='p3event_pythonTask.obj') - TargetAdd('core.pyd', input='p3gobj_geomVertexArrayData_ext.obj') - TargetAdd('core.pyd', input='p3gobj_internalName_ext.obj') + TargetAdd('core.pyd', input='p3gobj_ext_composite.obj') TargetAdd('core.pyd', input='p3pgraph_ext_composite.obj') TargetAdd('core.pyd', input='p3display_graphicsStateGuardian_ext.obj') TargetAdd('core.pyd', input='p3display_graphicsWindow_ext.obj') diff --git a/panda/src/express/pointerToArray_ext.I b/panda/src/express/pointerToArray_ext.I index da1f897300..c53b0c3ee0 100644 --- a/panda/src/express/pointerToArray_ext.I +++ b/panda/src/express/pointerToArray_ext.I @@ -24,11 +24,6 @@ template void Extension >:: __init__(PyObject *self, PyObject *source) { - // We have to pre-initialize self's "this" pointer when we receive - // self in the constructor--the caller can't initialize this for us. - new (this->_this) PointerToArray(get_type_handle(Element)); - ((Dtool_PyInstDef *)self)->_ptr_to_object = this->_this; - #if PY_VERSION_HEX >= 0x02060000 if (PyObject_CheckBuffer(source)) { // User passed a buffer object. diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index 8b71bfac5a..7ac03ff431 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -8,7 +8,8 @@ #define LOCAL_LIBS \ p3pstatclient p3event p3linmath p3mathutil p3pnmimage p3gsgbase p3putil - #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx + #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx \ + $[TARGET]_ext_composite.cxx #define SOURCES \ adaptiveLru.I adaptiveLru.h \ @@ -30,7 +31,7 @@ geomLinestrips.h \ geomPoints.h \ geomVertexArrayData.h geomVertexArrayData.I \ - geomVertexArrayData_ext.h geomVertexArrayData_ext.cxx \ + geomVertexArrayData_ext.h \ geomVertexArrayFormat.h geomVertexArrayFormat.I \ geomCacheEntry.h geomCacheEntry.I \ geomCacheManager.h geomCacheManager.I \ @@ -43,7 +44,7 @@ geomVertexWriter.h geomVertexWriter.I \ indexBufferContext.I indexBufferContext.h \ internalName.I internalName.h \ - internalName_ext.h internalName_ext.cxx \ + internalName_ext.h \ lens.h lens.I \ material.I material.h materialPool.I materialPool.h \ matrixLens.I matrixLens.h \ @@ -82,7 +83,7 @@ vertexSlider.I vertexSlider.h \ vertexTransform.I vertexTransform.h \ videoTexture.I videoTexture.h - + #define INCLUDED_SOURCES \ adaptiveLru.cxx \ animateVerticesRequest.cxx \ @@ -103,6 +104,7 @@ geomLinestrips.cxx \ geomPoints.cxx \ geomVertexArrayData.cxx \ + geomVertexArrayData_ext.cxx \ geomVertexArrayFormat.cxx \ geomCacheEntry.cxx \ geomCacheManager.cxx \ @@ -116,6 +118,7 @@ indexBufferContext.cxx \ material.cxx \ internalName.cxx \ + internalName_ext.cxx \ lens.cxx \ materialPool.cxx matrixLens.cxx \ occlusionQueryContext.cxx \ @@ -131,6 +134,7 @@ sliderTable.cxx \ texture.cxx \ textureCollection.cxx \ + textureCollection_ext.cxx \ textureContext.cxx \ texturePeeker.cxx \ texturePool.cxx \ diff --git a/panda/src/gobj/p3gobj_ext_composite.cxx b/panda/src/gobj/p3gobj_ext_composite.cxx new file mode 100644 index 0000000000..33584e701b --- /dev/null +++ b/panda/src/gobj/p3gobj_ext_composite.cxx @@ -0,0 +1,3 @@ +#include "internalName_ext.cxx" +#include "geomVertexArrayData_ext.cxx" +#include "textureCollection_ext.cxx" diff --git a/panda/src/gobj/textureCollection.cxx b/panda/src/gobj/textureCollection.cxx index 6bddb5f199..40e8651edb 100644 --- a/panda/src/gobj/textureCollection.cxx +++ b/panda/src/gobj/textureCollection.cxx @@ -49,79 +49,6 @@ operator = (const TextureCollection ©) { _textures = copy._textures; } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: TextureCollection::Constructor -// Access: Published -// Description: This special constructor accepts a Python list of -// Textures. Since this constructor accepts a generic -// PyObject *, it should be the last constructor listed -// in the class record. -//////////////////////////////////////////////////////////////////// -TextureCollection:: -TextureCollection(PyObject *self, PyObject *sequence) { - // We have to pre-initialize self's "this" pointer when we receive - // self in the constructor--the caller can't initialize this for us. - ((Dtool_PyInstDef *)self)->_ptr_to_object = this; - - if (!PySequence_Check(sequence)) { - // If passed with a non-sequence, this isn't the right constructor. - PyErr_SetString(PyExc_TypeError, "TextureCollection constructor requires a sequence"); - return; - } - - int size = PySequence_Size(sequence); - for (int i = 0; i < size; ++i) { - PyObject *item = PySequence_GetItem(sequence, i); - if (item == NULL) { - return; - } - PyObject *result = PyObject_CallMethod(self, (char *)"add_texture", (char *)"O", item); - Py_DECREF(item); - if (result == NULL) { - // Unable to add item--probably it wasn't of the appropriate type. - ostringstream stream; - stream << "Element " << i << " in sequence passed to TextureCollection constructor could not be added"; - string str = stream.str(); - PyErr_SetString(PyExc_TypeError, str.c_str()); - return; - } - Py_DECREF(result); - } -} -#endif // HAVE_PYTHON - -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: TextureCollection::__reduce__ -// Access: Published -// Description: This special Python method is implement to provide -// support for the pickle module. -//////////////////////////////////////////////////////////////////// -PyObject *TextureCollection:: -__reduce__(PyObject *self) const { - // Here we will return a 4-tuple: (Class, (args), None, iterator), - // where iterator is an iterator that will yield successive - // Textures. - - // 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 - // object. - - PyObject *this_class = PyObject_Type(self); - if (this_class == NULL) { - return NULL; - } - - // Since a TextureCollection is itself an iterator, we can simply - // pass it as the fourth tuple component. - PyObject *result = Py_BuildValue("(O()OO)", this_class, Py_None, self); - Py_DECREF(this_class); - return result; -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: TextureCollection::add_texture // Access: Published @@ -270,6 +197,18 @@ clear() { _textures.clear(); } +//////////////////////////////////////////////////////////////////// +// Function: TextureCollection::reserve +// Access: Published +// Description: This is a hint to Panda to allocate enough memory +// to hold the given number of NodePaths, if you know +// ahead of time how many you will be adding. +//////////////////////////////////////////////////////////////////// +void TextureCollection:: +reserve(size_t num) { + _textures.reserve(num); +} + //////////////////////////////////////////////////////////////////// // Function: TextureCollection::find_texture // Access: Published diff --git a/panda/src/gobj/textureCollection.h b/panda/src/gobj/textureCollection.h index 38d3dc6faa..9be7b78f88 100644 --- a/panda/src/gobj/textureCollection.h +++ b/panda/src/gobj/textureCollection.h @@ -32,8 +32,8 @@ PUBLISHED: INLINE ~TextureCollection(); #ifdef HAVE_PYTHON - TextureCollection(PyObject *self, PyObject *sequence); - PyObject *__reduce__(PyObject *self) const; + EXTENSION(TextureCollection(PyObject *self, PyObject *sequence)); + EXTENSION(PyObject *__reduce__(PyObject *self) const); #endif void add_texture(Texture *texture); @@ -43,6 +43,7 @@ PUBLISHED: void remove_duplicate_textures(); bool has_texture(Texture *texture) const; void clear(); + void reserve(size_t num); Texture *find_texture(const string &name) const; @@ -74,5 +75,3 @@ INLINE ostream &operator << (ostream &out, const TextureCollection &col) { #include "textureCollection.I" #endif - - diff --git a/panda/src/gobj/textureCollection_ext.cxx b/panda/src/gobj/textureCollection_ext.cxx new file mode 100644 index 0000000000..e90295430b --- /dev/null +++ b/panda/src/gobj/textureCollection_ext.cxx @@ -0,0 +1,94 @@ +// Filename: textureCollection_ext.cxx +// Created by: rdb (11Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "textureCollection_ext.h" + +#ifdef HAVE_PYTHON + +#ifndef CPPPARSER +extern struct Dtool_PyTypedObject Dtool_Texture; +#endif + +//////////////////////////////////////////////////////////////////// +// Function: TextureCollection::__init__ +// Access: Published +// Description: This special constructor accepts a Python list of +// Textures. Since this constructor accepts a generic +// PyObject *, it should be the last constructor listed +// in the class record. +//////////////////////////////////////////////////////////////////// +void Extension:: +__init__(PyObject *self, PyObject *sequence) { + PyObject *fast = PySequence_Fast(sequence, "TextureCollection constructor requires a sequence"); + if (fast == NULL) { + return; + } + + Py_ssize_t size = PySequence_Fast_GET_SIZE(fast); + _this->reserve(size); + + for (int i = 0; i < size; ++i) { + PyObject *item = PySequence_Fast_GET_ITEM(fast, i); + if (item == NULL) { + return; + } + + Texture *tex; + DTOOL_Call_ExtractThisPointerForType(item, &Dtool_Texture, (void **)&tex); + if (tex == (Texture *)NULL) { + // Unable to add item--probably it wasn't of the appropriate type. + ostringstream stream; + stream << "Element " << i << " in sequence passed to TextureCollection constructor is not a Texture"; + string str = stream.str(); + PyErr_SetString(PyExc_TypeError, str.c_str()); + Py_DECREF(fast); + return; + } else { + _this->add_texture(tex); + } + } + + Py_DECREF(fast); +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureCollection::__reduce__ +// Access: Published +// Description: This special Python method is implement to provide +// support for the pickle module. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +__reduce__(PyObject *self) const { + // Here we will return a 4-tuple: (Class, (args), None, iterator), + // where iterator is an iterator that will yield successive + // Textures. + + // 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 + // object. + + PyObject *this_class = PyObject_Type(self); + if (this_class == NULL) { + return NULL; + } + + // Since a TextureCollection is itself an iterator, we can simply + // pass it as the fourth tuple component. + PyObject *result = Py_BuildValue("(O()OO)", this_class, Py_None, self); + Py_DECREF(this_class); + return result; +} + +#endif // HAVE_PYTHON diff --git a/panda/src/gobj/textureCollection_ext.h b/panda/src/gobj/textureCollection_ext.h new file mode 100644 index 0000000000..2818782e6a --- /dev/null +++ b/panda/src/gobj/textureCollection_ext.h @@ -0,0 +1,42 @@ +// Filename: textureCollection_ext.h +// Created by: rdb (11Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 TEXTURECOLLECTION_EXT_H +#define TEXTURECOLLECTION_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "textureCollection.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// TextureCollection, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + void __init__(PyObject *self, PyObject *sequence); + + PyObject *__reduce__(PyObject *self) const; +}; + +#endif // HAVE_PYTHON + +#endif // TEXTURECOLLECTION_EXT_H diff --git a/panda/src/pgraph/nodePathCollection.cxx b/panda/src/pgraph/nodePathCollection.cxx index bd3ddfbcc6..c704543838 100644 --- a/panda/src/pgraph/nodePathCollection.cxx +++ b/panda/src/pgraph/nodePathCollection.cxx @@ -20,10 +20,6 @@ #include "colorAttrib.h" #include "indent.h" -#ifdef HAVE_PYTHON -#include "py_panda.h" -#endif - //////////////////////////////////////////////////////////////////// // Function: NodePathCollection::Constructor // Access: Published @@ -54,48 +50,6 @@ operator = (const NodePathCollection ©) { _node_paths = copy._node_paths; } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: NodePathCollection::Constructor -// Access: Published -// Description: This special constructor accepts a Python list of -// NodePaths. Since this constructor accepts a generic -// PyObject *, it should be the last constructor listed -// in the class record. -//////////////////////////////////////////////////////////////////// -NodePathCollection:: -NodePathCollection(PyObject *self, PyObject *sequence) { - // We have to pre-initialize self's "this" pointer when we receive - // self in the constructor--the caller can't initialize this for us. - ((Dtool_PyInstDef *)self)->_ptr_to_object = this; - - if (!PySequence_Check(sequence)) { - // If passed with a non-sequence, this isn't the right constructor. - PyErr_SetString(PyExc_TypeError, "NodePathCollection constructor requires a sequence"); - return; - } - - int size = PySequence_Size(sequence); - for (int i = 0; i < size; ++i) { - PyObject *item = PySequence_GetItem(sequence, i); - if (item == NULL) { - return; - } - PyObject *result = PyObject_CallMethod(self, (char *)"addPath", (char *)"O", item); - Py_DECREF(item); - if (result == NULL) { - // Unable to add item--probably it wasn't of the appropriate type. - ostringstream stream; - stream << "Element " << i << " in sequence passed to NodePathCollection constructor could not be added"; - string str = stream.str(); - PyErr_SetString(PyExc_TypeError, str.c_str()); - return; - } - Py_DECREF(result); - } -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: NodePathCollection::add_path // Access: Published @@ -244,6 +198,18 @@ clear() { _node_paths.clear(); } +//////////////////////////////////////////////////////////////////// +// Function: NodePathCollection::reserve +// Access: Published +// Description: This is a hint to Panda to allocate enough memory +// to hold the given number of NodePaths, if you know +// ahead of time how many you will be adding. +//////////////////////////////////////////////////////////////////// +void NodePathCollection:: +reserve(size_t num) { + _node_paths.reserve(num); +} + //////////////////////////////////////////////////////////////////// // Function: NodePathCollection::is_empty // Access: Published @@ -335,7 +301,7 @@ find_all_matches(const string &path) const { if (!is_empty()) { FindApproxLevelEntry *level = NULL; for (int i = 0; i < get_num_paths(); i++) { - FindApproxLevelEntry *start = + FindApproxLevelEntry *start = new FindApproxLevelEntry(get_path(i), approx_path); start->_next = level; level = start; diff --git a/panda/src/pgraph/nodePathCollection.h b/panda/src/pgraph/nodePathCollection.h index 6265f85d16..8527db5b5d 100644 --- a/panda/src/pgraph/nodePathCollection.h +++ b/panda/src/pgraph/nodePathCollection.h @@ -34,7 +34,7 @@ PUBLISHED: INLINE ~NodePathCollection(); #ifdef HAVE_PYTHON - NodePathCollection(PyObject *self, PyObject *sequence); + EXTENSION(NodePathCollection(PyObject *self, PyObject *sequence)); EXTENSION(PyObject *__reduce__(PyObject *self) const); #endif @@ -45,6 +45,7 @@ PUBLISHED: void remove_duplicate_paths(); bool has_path(const NodePath &path) const; void clear(); + void reserve(size_t num); bool is_empty() const; int get_num_paths() const; diff --git a/panda/src/pgraph/nodePathCollection_ext.cxx b/panda/src/pgraph/nodePathCollection_ext.cxx index 7499381320..48898fb547 100644 --- a/panda/src/pgraph/nodePathCollection_ext.cxx +++ b/panda/src/pgraph/nodePathCollection_ext.cxx @@ -17,6 +17,7 @@ #ifdef HAVE_PYTHON #ifndef CPPPARSER +extern struct Dtool_PyTypedObject Dtool_NodePath; #ifdef STDFLOAT_DOUBLE extern struct Dtool_PyTypedObject Dtool_LPoint3d; #else @@ -24,6 +25,48 @@ extern struct Dtool_PyTypedObject Dtool_LPoint3f; #endif #endif +//////////////////////////////////////////////////////////////////// +// Function: NodePathCollection::__init__ +// Access: Published +// Description: This special constructor accepts a Python list of +// NodePaths. Since this constructor accepts a generic +// PyObject *, it should be the last constructor listed +// in the class record. +//////////////////////////////////////////////////////////////////// +void Extension:: +__init__(PyObject *self, PyObject *sequence) { + PyObject *fast = PySequence_Fast(sequence, "NodePathCollection constructor requires a sequence"); + if (fast == NULL) { + return; + } + + Py_ssize_t size = PySequence_Fast_GET_SIZE(fast); + _this->reserve(size); + + for (int i = 0; i < size; ++i) { + PyObject *item = PySequence_Fast_GET_ITEM(fast, i); + if (item == NULL) { + return; + } + + NodePath *path; + DTOOL_Call_ExtractThisPointerForType(item, &Dtool_NodePath, (void **)&path); + if (path == (NodePath *)NULL) { + // Unable to add item--probably it wasn't of the appropriate type. + ostringstream stream; + stream << "Element " << i << " in sequence passed to NodePathCollection constructor is not a NodePath"; + string str = stream.str(); + PyErr_SetString(PyExc_TypeError, str.c_str()); + Py_DECREF(fast); + return; + } else { + _this->add_path(*path); + } + } + + Py_DECREF(fast); +} + //////////////////////////////////////////////////////////////////// // Function: NodePathCollection::__reduce__ // Access: Published @@ -83,4 +126,4 @@ get_tight_bounds() const { } } -#endif +#endif // HAVE_PYTHON diff --git a/panda/src/pgraph/nodePathCollection_ext.h b/panda/src/pgraph/nodePathCollection_ext.h index 62cee4cc94..60aa2203ec 100644 --- a/panda/src/pgraph/nodePathCollection_ext.h +++ b/panda/src/pgraph/nodePathCollection_ext.h @@ -32,6 +32,8 @@ template<> class Extension : public ExtensionBase { public: + void __init__(PyObject *self, PyObject *sequence); + PyObject *__reduce__(PyObject *self) const; PyObject *get_tight_bounds() const;