[C++-sig] [pybindgen] Problems on class constructor
Gustavo Carneiro
gjcarneiro at gmail.com
Thu Aug 21 20:05:10 CEST 2008
2008/8/21 Gustavo Carneiro <gjcarneiro at gmail.com>
>
>
> 2008/8/21 Olaf Peter <ope-devel at gmx.de>
>
> Hi,
>>
>> given the following header:
>>
>> ---8<---
>> class PyConsole;
>>
>> class StdoutPy
>> {
>> public:
>> StdoutPy(PyConsole* console);
>> void write(PyObject* args);
>> void flush();
>> private:
>> PyConsole* m_console;
>> };
>>
>> class PyConsole
>> {
>> void writeOut(PyObject* args);
>> void writeErr(PyObject* args);
>> void flush();
>> };
>> --->8---
>>
>>
>> and the python script:
>>
>> ---8<---
>> import pybindgen
>> import sys
>>
>> # convenience
>> param=pybindgen.param
>> retval=pybindgen.retval
>>
>> pybindgen.settings.min_python_version = (2,5)
>>
>> mod = pybindgen.Module('redirector')
>> mod.add_include('"redirector.hpp"')
>>
>> stdout_py = mod.add_class('StdoutPy')
>> stdout_py.add_constructor([param('PyConsole*', 'cpp_parent',
>> transfer_ownership=False)])
>> stdout_py.add_method('write', None, [param('PyObject*', 'value',
>> transfer_ownership=False)])
>> stdout_py.add_method('flush', None, [])
>>
>> mod.generate(sys.stdout)
>> --->8---
>>
>> I get the error:
>>
>> $ python redirector.py
>> Traceback (most recent call last):
>> File "redirector.py", line 14, in <module>
>> stdout_py.add_constructor([param('PyConsole*', 'cpp_parent',
>> transfer_ownership=False)])
>> File "/usr/lib/python2.5/site-packages/pybindgen/cppclass.py", line
>> 1228, in add_constructor
>> constructor = CppConstructor(*args, **kwargs)
>> File "/usr/lib/python2.5/site-packages/pybindgen/cppmethod.py", line
>> 415, in __init__
>> parameters = [utils.eval_param(param, self) for param in parameters]
>> File "/usr/lib/python2.5/site-packages/pybindgen/utils.py", line 205,
>> in eval_param
>> TypeLookupError))
>> File "/usr/lib/python2.5/site-packages/pybindgen/utils.py", line 115,
>> in call_with_error_handling
>> return callable(*args, **kwargs)
>> File
>> "/usr/lib/python2.5/site-packages/pybindgen/typehandlers/base.py", line
>> 1167, in new
>> param_type_matcher.lookup(ctype)
>> File
>> "/usr/lib/python2.5/site-packages/pybindgen/typehandlers/base.py", line
>> 1300, in lookup
>> raise TypeLookupError(name)
>> pybindgen.typehandlers.base.TypeLookupError: PyConsole *
>>
>>
>> It seems, that I have to register my own types but I have no idea how to
>> do this.
>
>
> You just have to declare the PyConsole class, with:
> mod.add_class('PyConsole')
>
> For Testing I've used the xmlgcc approach:
>>
>> ---8<---
>> import sys
>>
>> from pybindgen import FileCodeSink
>> from pybindgen.gccxmlparser import ModuleParser
>>
>> def my_module_gen():
>> module_parser = ModuleParser('redirector', '::')
>> module_parser.parse([sys.argv[1]],
>> include_paths=['/usr/include/python2.5'],includes=['"redirector.hpp"'],
>> pygen_sink=FileCodeSink(sys.stdout))
>>
>> if __name__ == '__main__':
>> my_module_gen()
>> --->8---
>>
>> which results in errors too:
>>
>> /usr/lib/python2.5/site-packages/pybindgen/gccxmlparser.py:580:
>> DeprecationWarning: Parameter include_paths is deprecated, use
>> gccxml_options instead
>> self.parse_init(header_files, include_paths, whitelist_paths,
>> includes, pygen_sink, pygen_classifier)
>>
>> INFO Parsing source file "redirector.hpp" ...
>>
>> INFO gccxml cmd: /usr/bin/gccxml -I"." -I"/usr/include/python2.5"
>> "redirector.hpp" -fxml="/tmp/tmp5ORqw3.xml"
>>
>> INFO GCCXML version - 0.7
>> /usr/lib/python2.5/site-packages/pygccxml/parser/scanner.py:335:
>> UserWarning: unable to find out array size from expression ""
>> warnings.warn( msg )
>> from pybindgen import Module, FileCodeSink, param, retval, cppclass
>>
>>
>> import pybindgen.settings
>> import warnings
>>
>> class ErrorHandler(pybindgen.settings.ErrorHandler):
>> def handle_error(self, wrapper, exception, traceback_):
>> warnings.warn("exception %r in wrapper %s" % (exception, wrapper))
>> return True
>> pybindgen.settings.error_handler = ErrorHandler()
>>
>>
>> import sys
>>
>> def module_init():
>> root_module = Module('redirector', cpp_namespace='::')
>> root_module.add_include('"redirector.hpp"')
>> return root_module
>>
>> def register_types(module):
>> root_module = module.get_root()
>>
>> module.add_class('StdoutPy')
>> module.add_class('PyConsole')
>>
>> ## Register a nested module for the namespace std
>>
>> nested_module = module.add_cpp_namespace('std')
>> register_types_std(nested_module)
>>
>>
>> def register_types_std(module):
>> root_module = module.get_root()
>>
>>
>> def register_methods(root_module):
>> register_StdoutPy_methods(root_module, root_module['StdoutPy'])
>> register_PyConsole_methods(root_module, root_module['PyConsole'])
>> return
>>
>> def register_StdoutPy_methods(root_module, cls):
>> /usr/lib/python2.5/site-packages/pybindgen/gccxmlparser.py:215:
>> UserWarning: multiple &'s not handled
>> warnings.warn("multiple &'s not handled")
>> /usr/lib/python2.5/site-packages/pybindgen/gccxmlparser.py:211:
>> UserWarning: multiple consts not handled
>> warnings.warn("multiple consts not handled")
>> cls.add_constructor([param('StdoutPy&', '_ctor_arg', is_const=True)])
>> cls.add_constructor([param('PyConsole *', 'console')])
>> /var/tmp/redirector.hpp:12: WrapperWarning: Parameter '::PyConsole *
>> console' error (used in StdoutPy::StdoutPy(PyConsole * console)
>> [constructor]): TypeConfigurationError('transfer_ownership parameter
>> missing',)
>> StdoutPy(PyConsole* console);
>> cls.add_method('write',
>> 'void',
>> [param('PyObject *', 'args')])
>> /usr/lib/python2.5/site-packages/pybindgen/typehandlers/base.py:1173:
>> UserWarning: Exception '__init__() takes at least 4 arguments (3 given)'
>> in type handler <class
>> 'pybindgen.typehandlers.pyobjecttype.PyObjectParam'> constructor
>> warnings.warn("Exception %r in type handler %s constructor" %
>> (str(ex), type_handler_class))
>> Traceback (most recent call last):
>> File "redirector_py.py", line 13, in <module>
>> my_module_gen()
>> File "redirector_py.py", line 10, in my_module_gen
>> module_parser.parse([sys.argv[1]],
>> include_paths=['/usr/include/python2.5'],includes=['"redirector.hpp"'],
>> pygen_sink=FileCodeSink(sys.stdout))
>> File "/usr/lib/python2.5/site-packages/pybindgen/gccxmlparser.py",
>> line 582, in parse
>> self.scan_methods()
>> File "/usr/lib/python2.5/site-packages/pybindgen/gccxmlparser.py",
>> line 809, in scan_methods
>> self._scan_class_methods(class_wrapper.gccxml_definition,
>> class_wrapper, pygen_sink)
>> File "/usr/lib/python2.5/site-packages/pybindgen/gccxmlparser.py",
>> line 1420, in _scan_class_methods
>> arguments.append(Parameter.new(*arg[0], **arg[1]))
>> File
>> "/usr/lib/python2.5/site-packages/pybindgen/typehandlers/base.py", line
>> 1171, in new
>> return type_handler_class(*args, **kwargs)
>> TypeError: __init__() takes at least 4 arguments (3 given)
>
>
> I am guessing you need to add a transfer_ownership=false annotation in some
> places. I know, annotations are not properly documented, so I don't blame
> you for the mistake :P
>
> I think your header file would need something like this (check the -#-
> comments):
>
> class PyConsole;
>
> class StdoutPy
> {
> public:
> // -#- @console(transfer_ownership=false) -#-
> StdoutPy(PyConsole* console);
> // -#- @args(transfer_ownership=false) -#-
> void write(PyObject* args);
> void flush();
> private:
> PyConsole* m_console;
> };
>
> class PyConsole
> {
> // -#- @args(transfer_ownership=false) -#-
> void writeOut(PyObject* args);
> // -#- @args(transfer_ownership=false) -#-
> void writeErr(PyObject* args);
> void flush();
> };
>
>
>>
>> BTW, how can I prevent the construction of the StdoutPy class from
>> python? It has to be created from c++ side.
>>
>
> Using gccxml scanner, there's no easy way to do it. I guess that, after
> scanning, you can reset the list of constructors to the empty list:
> module['StdoutPy'].constructors = []
>
After hitting send I remembered... A less hackish way to do it with the
gccxml scanner is to add 'ignore' annotations to the constructors.
class PyConsole
{
public:
// -#- ignore -#-
PyConsole () {} // need to make the constructor explicit for this to
work...
[...]
};
P. S.: the annotations system is rather fragile. Annotations are looked for
in the line above the line where GCC-XML reports that the declaration is
defined. But GCC-XML reports weird line numbers on multi-line declarations,
so beware.
--
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20080821/8e33b6c4/attachment.htm>
More information about the Cplusplus-sig
mailing list