C++ clas with (*args, **kwargs) constructor
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
From: Trigve Siver <trigves@yahoo.com> To: Development of Python/C++ integration <cplusplus-sig@python.org> Cc: Sent: Thursday, June 21, 2012 11:31 PM Subject: [C++-sig] C++ clas with (*args, **kwargs) constructor
... 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(); }
Bad formatting, sorry: 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(); }
...
Trigve
On 06/21/2012 05:31 PM, Trigve Siver 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:
I believe this is not possible in Boost.Python. The closest approximations I know of are: - Use a static method or free function instead of a constructor for this mode of construction in Python. You can wrap a non-constructor with *args, **kwds using boost::python::raw_function. - Inherit from the wrapped class at the Python layer; the derived class could then have a constructor with *args, **kwds. Jim
From: Jim Bosch <talljimbo@gmail.com> To: cplusplus-sig@python.org Cc: Sent: Thursday, June 21, 2012 11:57 PM Subject: Re: [C++-sig] C++ clas with (*args, **kwargs) constructor
On 06/21/2012 05:31 PM, Trigve Siver 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:
I believe this is not possible in Boost.Python. The closest approximations I know of are:
- Use a static method or free function instead of a constructor for this mode of construction in Python. You can wrap a non-constructor with *args, **kwds using boost::python::raw_function.
- Inherit from the wrapped class at the Python layer; the derived class could then have a constructor with *args, **kwds.
Thanks for reply :) Hmm I was trying with python::raw_function, but without success also. Ok I'm gonna try a bit more with raw_constructor once more. Thanks
Jim
Trigve
On 06/21/2012 06:07 PM, Trigve Siver wrote:
From: Jim Bosch <talljimbo@gmail.com> To: cplusplus-sig@python.org Cc: Sent: Thursday, June 21, 2012 11:57 PM Subject: Re: [C++-sig] C++ clas with (*args, **kwargs) constructor
On 06/21/2012 05:31 PM, Trigve Siver 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:
I believe this is not possible in Boost.Python. The closest approximations I know of are:
- Use a static method or free function instead of a constructor for this mode of construction in Python. You can wrap a non-constructor with *args, **kwds using boost::python::raw_function.
- Inherit from the wrapped class at the Python layer; the derived class could then have a constructor with *args, **kwds.
Thanks for reply :) Hmm I was trying with python::raw_function, but without success also. Ok I'm gonna try a bit more with raw_constructor once more.
Heh, I didn't even know about raw_constructor, because it isn't in the reference docs for some reason. If it exists, then your problem very likely is solvable and my response was totally bogus. Glad I didn't discourage you. Jim
From: Jim Bosch <talljimbo@gmail.com> To: cplusplus-sig@python.org Cc: Sent: Friday, June 22, 2012 12:28 AM Subject: Re: [C++-sig] C++ clas with (*args, **kwargs) constructor
From: Jim Bosch <talljimbo@gmail.com> To: cplusplus-sig@python.org Cc: Sent: Thursday, June 21, 2012 11:57 PM Subject: Re: [C++-sig] C++ clas with (*args, **kwargs) constructor
On 06/21/2012 05:31 PM, Trigve Siver 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
of constructor? I've tried something like this:
I believe this is not possible in Boost.Python. The closest approximations I know of are:
- Use a static method or free function instead of a constructor for
On 06/21/2012 06:07 PM, Trigve Siver wrote: this kind this mode of
construction in Python. You can wrap a non-constructor with *args, **kwds using boost::python::raw_function.
- Inherit from the wrapped class at the Python layer; the derived class could then have a constructor with *args, **kwds.
Thanks for reply :) Hmm I was trying with python::raw_function, but without success also. Ok I'm gonna try a bit more with raw_constructor once more.
Heh, I didn't even know about raw_constructor, because it isn't in the reference docs for some reason. If it exists, then your problem very likely is solvable and my response was totally bogus.
This raw_constructor isn't integrated in boost:python. It is from http://wiki.python.org/moin/boost.python/HowTo#A.22Raw.22_constructor as mentioned in previous mail. Maybe there is a little chance to make patch and add it to boost::python? :)
Glad I didn't discourage you.
:)
Jim
Trigve
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@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@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig
From: Holger Brandsmeier <brandsmeier@gmx.de> To: Trigve Siver <trigves@yahoo.com>; Development of Python/C++ integration <cplusplus-sig@python.org> Cc: Sent: Thursday, June 21, 2012 11:58 PM Subject: Re: [C++-sig] C++ clas with (*args, **kwargs) constructor
T rigve,
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?
Thanks for reply :) Ok it looks like it is working now :) When I used raw_constructor I have set min arguments to 2, like this: ... boost::shared_ptr<Form> create(tuple, dict) { return boost::shared_ptr<Form>(new Form()); } class_<Form, boost::noncopyable, boost::shared_ptr<Form>>("Form", no_init) .def("__init__", raw_constructor(&create, 2)) ... But when *args or **kwargs was empty (or both of them), it was spoiling errors. So I set min arguments to 0 (removed the parameter respectively). Hope I'm doing it right way.
...
-Holger
Thanks Trigve
participants (3)
-
Holger Brandsmeier -
Jim Bosch -
Trigve Siver