This commit is contained in:
Gustavo J. A. M. Carneiro committed 2009-11-17 16:03:47 +00:00
commit fa575f1ca7
1 file changed
+77 -9
+77 -9
View File
@@ -89,6 +89,13 @@ def remove_const(type):
###
## --- utility ---
import pygccxml.declarations.type_traits
def find_declaration_from_name(global_ns, declaration_name):
decl = pygccxml.declarations.type_traits.impl_details.find_value_type(global_ns, declaration_name)
return decl
class ModuleParserWarning(Warning):
"""
@@ -437,6 +444,19 @@ class PygenClassifier(object):
"""
raise NotImplementedError
def get_section_precedence(self, section_name):
"""
This is a pure virtual method that may (or not) be implemented by
subclasses. It will be called by PyBindGen for every API
definition, and should return the precedence of a section.
This is used when sections reflect 'modules' whose types must be
registered in a certain order.
@param section_name: the name of the section @returns: order
of precedence of the section. The lower the number, the
sooner the section is to be registered.
"""
raise NotImplementedError
class ModuleParser(object):
@@ -466,7 +486,8 @@ class ModuleParser(object):
self.whitelist_paths = []
self.module_namespace = None # pygccxml module C++ namespace
self.module = None # the toplevel pybindgen.module.Module instance (module being generated)
self.declarations = None # pygccxml.declarations.namespace.namespace_t (as returned by pygccxml.parser.parse)
self.declarations = None # (as returned by pygccxml.parser.parse)
self.global_ns = None
self._types_scanned = False
self._pre_scan_hooks = []
self._post_scan_hooks = []
@@ -651,12 +672,14 @@ class ModuleParser(object):
self.gccxml_config = parser.config_t(**gccxml_options)
self.declarations = parser.parse(header_files, self.gccxml_config)
self.global_ns = declarations.get_global_namespace(self.declarations)
if self.module_namespace_name == '::':
self.module_namespace = declarations.get_global_namespace(self.declarations)
self.module_namespace = self.global_ns
else:
self.module_namespace = declarations.get_global_namespace(self.declarations).\
namespace(self.module_namespace_name)
self.module_namespace = self.global_ns.namespace(self.module_namespace_name)
self.module = Module(self.module_name, cpp_namespace=self.module_namespace.decl_string)
for inc in includes:
self.module.add_include(inc)
@@ -715,7 +738,7 @@ pybindgen.settings.error_handler = ErrorHandler()
else:
return []
def _get_pygen_sink_for_definition(self, pygccxml_definition):
def _get_pygen_sink_for_definition(self, pygccxml_definition, with_section_precedence=False):
if self._pygen_classifier is None:
return self._pygen
else:
@@ -723,11 +746,21 @@ pybindgen.settings.error_handler = ErrorHandler()
section = self._pygen_classifier.classify(pygccxml_definition)
for sect in self._pygen:
if sect is section or sect.name == section:
return sect.code_sink
sink = sect.code_sink
break
else:
raise ValueError("CodeSink for section %r not available" % section)
else:
return self._get_main_pygen_sink()
sink = self._get_main_pygen_sink()
section = '__main__'
if with_section_precedence:
try:
prec = self._pygen_classifier.get_section_precedence(section)
except NotImplementedError:
prec = 0
return (prec, sink)
else:
return sink
def scan_types(self):
self._stage = 'scan types'
@@ -998,17 +1031,21 @@ pybindgen.settings.error_handler = ErrorHandler()
count = getattr(cls, "_pybindgen_postpone_count", 0)
count += 1
cls._pybindgen_postpone_count = count
if count >= 100:
if count >= 10:
raise AssertionError("The class %s registration is being postponed for "
"the %ith time (last reason: %r, current reason: %r);"
" something is wrong, please file a bug report"
" (https://bugs.launchpad.net/pybindgen/+filebug) with a test case."
% (cls, count, cls._pybindgen_postpone_reason, reason))
cls._pybindgen_postpone_reason = reason
if DEBUG:
print >> sys.stderr, ">>> class %s is being postponed (%s)" % (str(cls), reason)
unregistered_classes.append(cls)
while unregistered_classes:
cls = unregistered_classes.pop(0)
if DEBUG:
print >> sys.stderr, ">>> looking at class ", str(cls)
typedef = None
kwargs = {}
@@ -1109,6 +1146,26 @@ pybindgen.settings.error_handler = ErrorHandler()
cls_name = typedef.name
alias = '::'.join([module.cpp_namespace_prefix, cls.name])
template_parameters_decls = [find_declaration_from_name(self.global_ns, templ_param)
for templ_param in template_parameters]
if 0: # this is disabled due to ns3
## if any template argument is a class that is not yet
## registered, postpone scanning/registering the template
## instantiation class until the template argument gets
## registered.
postponed = False
for templ in template_parameters_decls:
if isinstance(templ, class_t):
try:
self._registered_classes[templ]
except KeyError:
if templ in unregistered_classes:
postpone_class(cls, "waiting for template argument class %s to be registered first" % templ)
postponed = True
if postponed:
continue
if base_class_wrapper is not None:
kwargs["parent"] = base_class_wrapper
if outer_class is not None:
@@ -1118,7 +1175,18 @@ pybindgen.settings.error_handler = ErrorHandler()
if custom_template_class_name:
kwargs["custom_name"] = custom_template_class_name
pygen_sink = self._get_pygen_sink_for_definition(cls)
# given the pygen sinks for the class itself and the sinks
# for the template parameters, get the one with lowest
# precedence (the higher the number, the lowest the
# precedence).
pygen_sinks = [self._get_pygen_sink_for_definition(cls, with_section_precedence=True)]
for templ in template_parameters_decls:
if templ is not None:
pygen_sinks.append(self._get_pygen_sink_for_definition(templ, with_section_precedence=True))
pygen_sinks.sort()
pygen_sink = pygen_sinks[-1][1]
del pygen_sinks
if pygen_sink:
if 'pygen_comment' in global_annotations:
pygen_sink.writeln('## ' + global_annotations['pygen_comment'])