Revision: 609
http://svn.sourceforge.net/pygccxml/?rev=609&view=rev
Author: mbaas
Date: 2006-09-29 09:45:03 -0700 (Fri, 29 Sep 2006)
Log Message:
-----------
1) Emulate the finalize functionality by modifying the decl_wrappers and post-processing the code creator tree. 2) Activate the extended code creator API. 3) Import all call policies at once instead of importing them one by one. 4) Fixed the Var()/Vars() methods. 5) Bugfix: Some decoration methods weren't returning self.
Modified Paths:
--------------
pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py
pyplusplus_dev/contrib/pypp_api/pypp_api/declwrapper.py
pyplusplus_dev/contrib/pypp_api/pypp_api/modulebuilder.py
Modified: pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py
===================================================================
--- pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py 2006-09-29 16:41:06 UTC (rev 608)
+++ pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py 2006-09-29 16:45:03 UTC (rev 609)
@@ -50,16 +50,17 @@
# Bring in call policies to use
-from pyplusplus.decl_wrappers import return_self
-from pyplusplus.decl_wrappers import return_internal_reference
-from pyplusplus.decl_wrappers import with_custodian_and_ward
-from pyplusplus.decl_wrappers import copy_const_reference
-from pyplusplus.decl_wrappers import copy_non_const_reference
-from pyplusplus.decl_wrappers import manage_new_object
-from pyplusplus.decl_wrappers import reference_existing_object
-from pyplusplus.decl_wrappers import return_by_value
-from pyplusplus.decl_wrappers import return_opaque_pointer
-from pyplusplus.decl_wrappers import return_value_policy
+from pyplusplus.decl_wrappers.call_policies import *
+#from pyplusplus.decl_wrappers import return_self
+#from pyplusplus.decl_wrappers import return_internal_reference
+#from pyplusplus.decl_wrappers import with_custodian_and_ward
+#from pyplusplus.decl_wrappers import copy_const_reference
+#from pyplusplus.decl_wrappers import copy_non_const_reference
+#from pyplusplus.decl_wrappers import manage_new_object
+#from pyplusplus.decl_wrappers import reference_existing_object
+#from pyplusplus.decl_wrappers import return_by_value
+#from pyplusplus.decl_wrappers import return_opaque_pointer
+#from pyplusplus.decl_wrappers import return_value_policy
from pygccxml.declarations import ACCESS_TYPES
PUBLIC = ACCESS_TYPES.PUBLIC
@@ -75,3 +76,5 @@
from pyplusplus.function_transformers.arg_policies import output_array_t as OutputArray
from modulebuilder import ModuleBuilder
+
+import extendcreators
Modified: pyplusplus_dev/contrib/pypp_api/pypp_api/declwrapper.py
===================================================================
--- pyplusplus_dev/contrib/pypp_api/pypp_api/declwrapper.py 2006-09-29 16:41:06 UTC (rev 608)
+++ pyplusplus_dev/contrib/pypp_api/pypp_api/declwrapper.py 2006-09-29 16:45:03 UTC (rev 609)
@@ -191,13 +191,48 @@
def finalize(self):
"""Finalize virtual member functions or an entire class.
- Prevents the generation of wrappers for virtual member functions.
+ This method can be called on classes or individual member functions
+ to prevent the generation of wrapper classes. This is done by
+ resetting the virtuality attribute of the members to "non-virtual"
+ and by ignoring protected and private member functions.
+ A ValueError exception is raised if the method is called on pure
+ virtual functions because those cannot be wrapped without a wrapper
+ class.
+
+ Even when finalize() was successfully called it is still possible
+ that Py++ generates a wrapper class nevertheless. The presence
+ of virtual member functions is only one part of the test whether
+ a wrapper class has to be generated (member variables can also
+ trigger a wrapper class which is not prevented by this method).
"""
self._checkLock()
+ VIRTUALITY_TYPES = pygccxml.declarations.VIRTUALITY_TYPES
for decl in self._iterContained():
+ # Mark the declaration as being finalized
+ decl._pypp_api_finalized = True
+
+ if not isinstance(decl, pygccxml.declarations.member_calldef_t):
+ continue
+
+ if (isinstance(decl, pyplusplus.decl_wrappers.constructor_t) or
+ isinstance(decl, pyplusplus.decl_wrappers.destructor_t)):
+ continue
+
+ if decl.virtuality==VIRTUALITY_TYPES.PURE_VIRTUAL:
+ raise ValueError, "%s\nMember is pure virtual and cannot be finalized."%decl
+
+ # Pretend that this method is a non-virtual method
+ decl.virtuality = VIRTUALITY_TYPES.NOT_VIRTUAL
+
if decoration_log!=None:
self._logDecoration("finalize", decl)
- decl.finalize()
+# decl.finalize()
+
+ # Ignore protected and private methods as these would trigger
+ # the generation of a wrapper class
+ ACCESS_TYPES = pygccxml.declarations.ACCESS_TYPES
+ self.Methods(accesstype=ACCESS_TYPES.PROTECTED, allow_empty=True).ignore()
+ self.Methods(accesstype=ACCESS_TYPES.PRIVATE, allow_empty=True).ignore()
return self
# setPolicy
@@ -213,6 +248,8 @@
self._logDecoration("setPolicy(...)", decl)
decl.call_policies = policy
+ return self
+
# setHeldType
def setHeldType(self, heldtype):
"""Explicitly set the held type.
@@ -257,6 +294,8 @@
decl.function_transformers.extend(list(policies))
# self.modulebuilder.mArgPolicyManager.setArgPolicy(decl, policies)
+ return self
+
# setAttr
def setAttr(self, attr, value):
"""Set an arbitrary attribute.
@@ -294,7 +333,7 @@
@param impl: The name of the C/C++ function that implements the method.
@type impl: str
"""
- self.cdef(name, impl)
+ return self.cdef(name, impl)
# def
@@ -377,6 +416,7 @@
header=None,
headerdir=None,
accesstype=None,
+ const=None,
filter=None,
recursive=None,
allow_empty=None,
@@ -429,6 +469,8 @@
@param headerdir: Select declarations by the directory in which their header file is located
@type headerdir: str
@param accesstype: Access type (PUBLIC or PROTECTED). This implies the type flag MEMBER_FUNCTION.
+ @param const: Select declarations by their constness.
+ @type const: bool
@param filter: User defined filter function
@type callable
@param recursive: Extend the search to grandchildren? If not specified, a global (customizable) default value is used.
@@ -484,6 +526,9 @@
if accesstype!=None:
addFilter(accesstype, AccessTypeFilter)
itype |= METHOD
+ # const filter
+ if const!=None:
+ addFilter(const, ConstFilter)
# custom filters
if filter!=None:
if _type(filter)==list:
@@ -577,7 +622,7 @@
# Vars
def Vars(self, name=None, type=0, **args):
- return self.Vars(name=name, type=type|VARIABLE, **args)
+ return self.Decls(name=name, type=type|VARIABLE, **args)
# Decl
def Decl(self, name=None, **args):
Modified: pyplusplus_dev/contrib/pypp_api/pypp_api/modulebuilder.py
===================================================================
--- pyplusplus_dev/contrib/pypp_api/pypp_api/modulebuilder.py 2006-09-29 16:41:06 UTC (rev 608)
+++ pyplusplus_dev/contrib/pypp_api/pypp_api/modulebuilder.py 2006-09-29 16:45:03 UTC (rev 609)
@@ -316,6 +316,9 @@
# maker = module_creator.creator_t(self.mFinalDecls, module_name=moduleName)
extmodule = maker.create(decl_headers=self.mHeaderFiles)
+ # Preprocess the tree
+ self._preprocessCreatorTree(extmodule)
+
# Let the arg policy manager update the tree...
self.mArgPolicyManager.updateCreators(extmodule)
@@ -526,6 +529,74 @@
self.mEndCreators.append(creator)
# ---------- Internal helpers ----------- #
+ def _preprocessCreatorTree(self, root):
+ """Preprocess the code creator tree.
+
+ Extends the nodes.
+
+ This method has to be called after the code creator tree was
+ generated by Py++.
+
+ @param root: The root of the code creator tree.
+ @type root: code_creator_t
+ """
+
+ # Iterate over the entire code creator tree...
+ for node in root.iter():
+ # If the code creator is based on a declaration, assign
+ # the code creator to the declaration. This makes it easy
+ # to obtain the corresponding code creator from a given
+ # decl_wrapper.
+ if isinstance(node, code_creators.declaration_based_t):
+ # Assign the code creator to the corresponding decl_wrapper
+ node.declaration.code_creator = node
+
+ # Is this a class wrapper creator? Then remove it if it was
+ # created on a finalized class
+ if isinstance(node, code_creators.class_wrapper_t):
+ finalized = getattr(node.declaration, "_pypp_api_finalized", False)
+ if finalized:
+ self._removeWrapperClass(node)
+
+ def _removeWrapperClass(self, wrappernode):
+ """Remove a wrapper class code creator.
+
+ All transformed member functions are moved out of the class
+ (as they are still needed) and then the wrapper class is removed.
+ """
+ class_creator = wrappernode.class_creator
+
+ # Search for members that have function transformers...
+ # (it is iterated over list(iter) so that the tree can be
+ # modified)
+ for node in list(wrappernode.iter()):
+ # Proceed to the next node if we are not dealing with a member
+ # function
+ if not isinstance(node, code_creators.calldef.calldef_wrapper_t):
+ continue
+
+ # Check if the node has function transformers.
+ # If this is the case we must keep that node and move it outside
+ # the wrapper class.
+ if node.declaration.function_transformers:
+ node.remove()
+ node.insertBefore(wrappernode)
+ class_creator.associated_decl_creators.append(node)
+
+ # Remove the class wrapper creator
+ wrappernode.remove()
+
+ # Remove all references to the wrapper creator (except on member
+ # functions with function transformers)
+ for node in class_creator.iter():
+ if not hasattr(node, "wrapper"):
+ continue
+ if isinstance(node, code_creators.calldef.calldef_t):
+ if node.declaration.function_transformers:
+ continue
+ node.wrapper = None
+
+
def buildTemplateFileContents(self):
""" Build up the contents of a file to instantiate the needed templates.
headerFiles - List of header files for this module.
@@ -719,4 +790,4 @@
self.__print_decl_header()
curr_level = self.level + 1
print ' ' * curr_level * self.INDENT_SIZE, 'type: %s value: %s'%(self.__inst.type.decl_string, self.__inst.value)
-
\ No newline at end of file
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|