Browse Source

Make NodePathCollection and TextureCollection constructors extensions

rdb 11 years ago
parent
commit
a6eb3fa442

+ 4 - 6
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";

+ 2 - 4
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')

+ 0 - 5
panda/src/express/pointerToArray_ext.I

@@ -24,11 +24,6 @@
 template<class Element>
 void Extension<PointerToArray<Element> >::
 __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<Element>(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.

+ 8 - 4
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 \

+ 3 - 0
panda/src/gobj/p3gobj_ext_composite.cxx

@@ -0,0 +1,3 @@
+#include "internalName_ext.cxx"
+#include "geomVertexArrayData_ext.cxx"
+#include "textureCollection_ext.cxx"

+ 12 - 73
panda/src/gobj/textureCollection.cxx

@@ -49,79 +49,6 @@ operator = (const TextureCollection &copy) {
   _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

+ 3 - 4
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
-
-

+ 94 - 0
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<TextureCollection>::
+__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<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

+ 42 - 0
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<TextureCollection>
+// Description : This class defines the extension methods for
+//               TextureCollection, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<TextureCollection> : public ExtensionBase<TextureCollection> {
+public:
+  void __init__(PyObject *self, PyObject *sequence);
+
+  PyObject *__reduce__(PyObject *self) const;
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // TEXTURECOLLECTION_EXT_H

+ 13 - 47
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 &copy) {
   _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;

+ 2 - 1
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;

+ 44 - 1
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<NodePathCollection>::
+__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

+ 2 - 0
panda/src/pgraph/nodePathCollection_ext.h

@@ -32,6 +32,8 @@
 template<>
 class Extension<NodePathCollection> : public ExtensionBase<NodePathCollection> {
 public:
+  void __init__(PyObject *self, PyObject *sequence);
+
   PyObject *__reduce__(PyObject *self) const;
 
   PyObject *get_tight_bounds() const;