create a python object from scratch in boost.python?
I'd like to create a python object with some attributes in C++, and return it to python. Something like this: Plugin_Info *pinfo = get_plugin_info_i(i); bp::object plugin; // this creates None; how can I make an empty class? plugin.attr("name") = std::string(pinfo->plugin_name); plugin.attr("category") = std::string(pinfo->category); plugin.attr("n_effects") = (int)pinfo->n_effects; plugin.attr("n_inputs") = (int)pinfo->n_inputs; plugin.attr("custom_p") = (int)pinfo->custom_p; effect_list.append(plugin); But this fails on the third line, because the "plugin" object is None, and None has no attributes. Instead of None, I'd like to create a simple empty python class I can add attributes to. How can I do that? (Yes, I could use a dict instead but the python side would like to see attributes with values rather than a dict.) -- . . . . . . . . . . . . . . . . . . . . . . Gary Oberbrunner garyo@genarts.com VP Engineering Tel: 617-492-2888 GenArts, Inc. www.genarts.com
Gary Oberbrunner wrote:
I'd like to create a python object with some attributes in C++, and return it to python. Something like this:
Plugin_Info *pinfo = get_plugin_info_i(i); bp::object plugin; // this creates None; how can I make an empty class? plugin.attr("name") = std::string(pinfo->plugin_name); plugin.attr("category") = std::string(pinfo->category); plugin.attr("n_effects") = (int)pinfo->n_effects; plugin.attr("n_inputs") = (int)pinfo->n_inputs; plugin.attr("custom_p") = (int)pinfo->custom_p; effect_list.append(plugin);
But this fails on the third line, because the "plugin" object is None, and None has no attributes. Instead of None, I'd like to create a simple empty python class I can add attributes to. How can I do that? (Yes, I could use a dict instead but the python side would like to see attributes with values rather than a dict.)
I think if you've exposed your c++ class, then there is a conversion from c++ object to python object. So bp::object plugin (Plugin_Info()); I believe would work.
----- Original Message -----
From: "Neal Becker" <ndbecker2@gmail.com> To: cplusplus-sig@python.org Sent: Monday, January 20, 2014 8:39:55 PM Subject: Re: [C++-sig] create a python object from scratch in boost.python?
Gary Oberbrunner wrote:
I'd like to create a python object with some attributes in C++, and return it to python. ... Instead of None, I'd like to create a simple empty python class I can add attributes to....
I think if you've exposed your c++ class, then there is a conversion from c++ object to python object. So
bp::object plugin (Plugin_Info());
Thanks -- I can indeed do that (or a proxy C++ class in any case). I was wondering though if it's possible to create an anonymous python class in BP, without a "starter" C++ class as it were. But I suppose that's mostly an academic question right now. -- Gary Oberbrunner
My be construct bp::object from the result of _PyObject_New? On Tue, Jan 21, 2014 at 8:29 AM, Gary Oberbrunner <garyo@genarts.com> wrote:
----- Original Message -----
From: "Neal Becker" <ndbecker2@gmail.com> To: cplusplus-sig@python.org Sent: Monday, January 20, 2014 8:39:55 PM Subject: Re: [C++-sig] create a python object from scratch in boost.python?
Gary Oberbrunner wrote:
I'd like to create a python object with some attributes in C++, and return it to python. ... Instead of None, I'd like to create a simple empty python class I can add attributes to....
I think if you've exposed your c++ class, then there is a conversion from c++ object to python object. So
bp::object plugin (Plugin_Info());
Thanks -- I can indeed do that (or a proxy C++ class in any case). I was wondering though if it's possible to create an anonymous python class in BP, without a "starter" C++ class as it were. But I suppose that's mostly an academic question right now.
-- Gary Oberbrunner _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org https://mail.python.org/mailman/listinfo/cplusplus-sig
...
I think if you've exposed your c++ class, then there is a conversion from c++ object to python object. So bp::object plugin (Plugin_Info());
Thanks -- I can indeed do that (or a proxy C++ class in any case). I was wondering though if it's possible to create an anonymous python class in BP, without a "starter" C++ class as it were. But I suppose that's mostly an academic question right now.
Well, it turns out I really do want to do this without a predefined C++ class, or something like that. I want to have the C++ code be easily extensible, so I don't have to repeat myself too much when adding new attributes. I tried making the proxy C++ class and exposing it, but it's very verbose and hard to maintain. I switched to using a dict, and what I have now is almost there: static bp::list EXTget_effects() { bp::list effect_list; int n_effects = get_n_sapphire_effects(); for (int i = 0; i < n_effects; i++) { Plugin_Info *pinfo = get_plugin_info_i(i); bp::dict ppinfo; ppinfo["name"] = (std::string)pinfo->plugin_name; ppinfo["category"] = (std::string)pinfo->category; ppinfo["n_effects"] = (int)pinfo->n_effects; ppinfo["n_inputs"] = (int)pinfo->n_inputs; ppinfo["custom_p"] = (int)pinfo->custom_p; effect_list.append(ppinfo); } return effect_list; } So now it returns a python list of python dicts. All I want now is to override __getattr__ on each ppinfo dict so it returns the dict value as the attribute value, so in python I can reference effect_list[i].name instead of effect_list[i]['name']. Or any alternative way to get the same effect. Is that possible? -- Gary Oberbrunner
On 01/21/2014 10:37 AM, Gary Oberbrunner wrote:
So now it returns a python list of python dicts. All I want now is to override __getattr__ on each ppinfo dict so it returns the dict value as the attribute value, so in python I can reference effect_list[i].name instead of effect_list[i]['name']. Or any alternative way to get the same effect. Is that possible? There are many ways to do that elegantly in Python. For example:
class Effect: def __init__(self, mydict): self.__dict__.update(mydict) If you want to combine that with existing classes / APIs, you could also consider merging the new attributes in via metaclasses. Stefan -- ...ich hab' noch einen Koffer in Berlin...
----- Original Message -----
From: "Stefan Seefeld" <stefan@seefeld.name> To: "Development of Python/C++ integration" <cplusplus-sig@python.org> Sent: Tuesday, January 21, 2014 10:45:52 AM Subject: Re: [C++-sig] create a python object from scratch in boost.python?
On 01/21/2014 10:37 AM, Gary Oberbrunner wrote:
So now it returns a python list of python dicts. All I want now is to override __getattr__ on each ppinfo dict so it returns the dict value as the attribute value, so in python I can reference effect_list[i].name instead of effect_list[i]['name']. Or any alternative way to get the same effect. Is that possible? There are many ways to do that elegantly in Python. For example:
class Effect: def __init__(self, mydict): self.__dict__.update(mydict)
I like the idea of using self.__dict__. If that's accessible from C++, then I suppose I could have an empty C++ class, export that as a simple container, and dynamically add attributes to it by manipulating its __dict__. Does that seem possible? -- Gary Oberbrunner
On 01/21/2014 11:03 AM, Gary Oberbrunner wrote:
----- Original Message -----
From: "Stefan Seefeld" <stefan@seefeld.name> To: "Development of Python/C++ integration" <cplusplus-sig@python.org> Sent: Tuesday, January 21, 2014 10:45:52 AM Subject: Re: [C++-sig] create a python object from scratch in boost.python?
On 01/21/2014 10:37 AM, Gary Oberbrunner wrote:
So now it returns a python list of python dicts. All I want now is to override __getattr__ on each ppinfo dict so it returns the dict value as the attribute value, so in python I can reference effect_list[i].name instead of effect_list[i]['name']. Or any alternative way to get the same effect. Is that possible? There are many ways to do that elegantly in Python. For example:
class Effect: def __init__(self, mydict): self.__dict__.update(mydict) I like the idea of using self.__dict__. If that's accessible from C++, then I suppose I could have an empty C++ class, export that as a simple container, and dynamically add attributes to it by manipulating its __dict__. Does that seem possible?
Why do you want to export an empty C++ class ? Do you have an API that would take that as argument or return type ? If not, I see no point in doing that, as all that does is provide implicit type conversion for you. It seems what you really want is a way for your C++ code to manipulate pure Python objects, without any automatic type conversion. So the cleanest way to do that would be to use the above definition of the "Effect" class (in Python), import that into your C++ runtime (via bpl::import()), and then instantiate an "Effect" object with your pre-defined dict object. bpl::object effect_type = bpl::import("Effect"); // Define Effect type in C++ runtime bpl::object effect = effect_type(ppinfo); // Instantiate Effect object with pre-defined attribute dictionary ... Stefan -- ...ich hab' noch einen Koffer in Berlin...
----- Original Message -----
From: "Stefan Seefeld" <stefan@seefeld.name> ... It seems what you really want is a way for your C++ code to manipulate pure Python objects, without any automatic type conversion.
Yes!
So the cleanest way to do that would be to use the above definition of the "Effect" class (in Python), import that into your C++ runtime (via bpl::import()), and then instantiate an "Effect" object with your pre-defined dict object.
I'm trying to do this in a boost python extension, so it has to be all in C++. If I have to wrap some python around it, it'll become a bit too heavyweight. I'd love to do what you suggest above, if it can be done all in C++. I think all I need is a way to create, in C++, an empty Python class object with a __dict__. Then, as you say, I can add attributes to it (at least I think I should be able to - but I'm not sure how far the boost.python world goes). -- Gary Oberbrunner
On 01/21/2014 01:52 PM, Gary Oberbrunner wrote:
----- Original Message -----
From: "Stefan Seefeld" <stefan@seefeld.name> ... It seems what you really want is a way for your C++ code to manipulate pure Python objects, without any automatic type conversion. Yes!
So the cleanest way to do that would be to use the above definition of the "Effect" class (in Python), import that into your C++ runtime (via bpl::import()), and then instantiate an "Effect" object with your pre-defined dict object. I'm trying to do this in a boost python extension, so it has to be all in C++. If I have to wrap some python around it, it'll become a bit too heavyweight.
Have a look at the attached code; I don't think that counts as heavy-weight. In particular, trying to do the same without embedding a little "script" would be just more cumbersome, if it worked at all.
I'd love to do what you suggest above, if it can be done all in C++. I think all I need is a way to create, in C++, an empty Python class object with a __dict__. Then, as you say, I can add attributes to it (at least I think I should be able to - but I'm not sure how far the boost.python world goes).
Compile the attached as a stand-alone app. I think it demonstrates what you want, so you should be able to easily adjust it to your use-case. Stefan -- ...ich hab' noch einen Koffer in Berlin...
----- Original Message -----
From: "Stefan Seefeld" <stefan@seefeld.name>
Have a look at the attached code; I don't think that counts as heavy-weight. In particular, trying to do the same without embedding a little "script" would be just more cumbersome, if it worked at all.
Whoa, that is cool! I had no idea boost python could do this. Thanks, Stefan! (It's like "python-ception": python calls C++ which calls python...) -- Gary Oberbrunner
On 01/21/2014 05:24 PM, Gary Oberbrunner wrote:
----- Original Message -----
From: "Stefan Seefeld" <stefan@seefeld.name> Have a look at the attached code; I don't think that counts as heavy-weight. In particular, trying to do the same without embedding a little "script" would be just more cumbersome, if it worked at all. Whoa, that is cool! I had no idea boost python could do this. Thanks, Stefan!
(It's like "python-ception": python calls C++ which calls python...)
Yeah, the boundary between the two languages really becomes blurry, precisely because the two really share the same runtime, so passing objects across the boundary becomes so seamless you can almost forget it's there. The beauty of hybrid programming... :-) Stefan -- ...ich hab' noch einen Koffer in Berlin...
participants (4)
-
Gary Oberbrunner -
Neal Becker -
Nikolay Mladenov -
Stefan Seefeld