[C++-sig] C++ clas with (*args, **kwargs) constructor

Holger Brandsmeier brandsmeier at gmx.de
Thu Jun 21 23:58:16 CEST 2012


Trigve,

with the line
  class_<Form, boost::noncopyable, boost::shared_ptr<Form>>("Form") ;
you declare Form to have a default constructor (you didn't use any
init<> struct. That is why you can not pass anything to the
constructor. If you want to use a constructor with a single (but
arbitrary) type, then you should use PyObject on the C++ side. Try to
get this working and tell us if this is how you want it to work, I
have a feeling that you already might not like having to manually
convert the PyObject* to the proper types. However, you can not avoid
it, you can not expect boost::python to automatically call a
constructor taking a single `int` if all that you export is a
constructor taking one `PyObject`, you will have to do the proper
conversions on the C++ side.

Second if you want to work with many objects of type PyObject* or even
`kwargs`, then
  http://wiki.python.org/moin/boost.python/HowTo#A.22Raw.22_constructor
is one option. I didn't really do this myself, but what is your problem there?

Possibly another object is, if you change the python side from
  super().__init__(*args, **kwargs)
to
  super().__init__(args, kwargs)
then you can write a C++ constructor which expects `list` and `dict`
and you will exactly find the contents of args passed as `list` and
`kwargs` as `dict`.

-Holger


On Thu, Jun 21, 2012 at 11:31 PM, Trigve Siver <trigves at yahoo.com> wrote:
>
>
> Hi,
> I'm trying to find some solution to my problem but without succes. I need to be able to export C++ class constructor that takes arbitraty arguments (as in python __init__(self, *args, **kwargs). Is it possible to have this kind of constructor? I've tried something like this:
>
> BOOST_PYTHON_MODULE(main)
> { class_<Form, boost::noncopyable, boost::shared_ptr<Form>>("Form") ;
> }
>
> then in main:
> ...
> try {
>         object main = import("__main__"); object global(main.attr("__dict__")); boost::python::dict local;
>         exec(   "import main\n" "class Form1(main.Form):\n" " def __init__(self, A, *args, **kwargs):\n" "  super().__init__(*args, **kwargs)\n\n" , global, local); // Get class object c_form1 = local["Form1"]; // Create instance object form1_instance = object(handle<>(PyObject_CallObject(c_form1.ptr(), make_tuple(1, 2).ptr())));
> }
> catch(error_already_set &)
> { PyErr_Print();
> }
>
> But it prints:
> Traceback (most recent call last):
> File "<string>", line 4, in __init__
> Boost.Python.ArgumentError: Python argument types in
> Form.__init__(Form1, int)
> did not match C++ signature:
> __init__(struct _object *)
>
> Which is logical I think because it finds only default constructor. I've tried also raw_constructor from http://wiki.python.org/moin/boost.python/HowTo#A.22Raw.22_constructor but without success.
>
> Anyone know if it is somehow possible?
>
> Thanks
>
> Trigve
>
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig


More information about the Cplusplus-sig mailing list