Thread: [pygccxml-development] special functions/operators
Brought to you by:
mbaas,
roman_yakovenko
From: Neal B. <ndb...@gm...> - 2006-08-25 14:26:11
|
Is there a way to add special functions/operators to a class? For example: struct X {}; X& addAssign (X& x1, X const& x2) { return x1; } // silly example I want this to do: .def ("__iadd__", addAssign, return_self<>()) |
From: Roman Y. <rom...@gm...> - 2006-08-25 16:49:30
|
On 8/25/06, Neal Becker <ndb...@gm...> wrote: > Is there a way to add special functions/operators to a class? > > For example: > > struct X {}; > X& addAssign (X& x1, X const& x2) { return x1; } // silly example > > I want this to do: > .def ("__iadd__", addAssign, return_self<>()) I think that if you rename addAssign to __iadd__ this will work, but I am not sure. mb.free_function( 'addAssign' ).rename( '__iadd__' ) -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Matthias B. <ba...@ir...> - 2006-08-25 17:09:02
|
Roman Yakovenko wrote: > On 8/25/06, Neal Becker <ndb...@gm...> wrote: >> Is there a way to add special functions/operators to a class? >> >> For example: >> >> struct X {}; >> X& addAssign (X& x1, X const& x2) { return x1; } // silly example >> >> I want this to do: >> .def ("__iadd__", addAssign, return_self<>()) > > I think that if you rename addAssign to __iadd__ this will work, but I > am not sure. > > mb.free_function( 'addAssign' ).rename( '__iadd__' ) I think this would only work when addAssign() was a member of X. I'm doing such things with the cdef() method of pypp_api which is equivalent to adding a raw def() statement to the class (I just had to name it something else because "def" is already a Python keyword). Usage of cdef is almost identical to Boost.Python's def. The first argument is the Python name, then comes the C/C++ function (as a string), followed by optional policies, args and doc string in arbitrary order. In the above example, it would look like this: root.Class("X").cdef("__iadd__", "addAssign", return_self()) (see https://realityforge.vrsource.org/view/PyppApi/Pypp_decorating) - Matthias - |
From: Roman Y. <rom...@gm...> - 2006-08-25 17:35:07
|
On 8/25/06, Matthias Baas <ba...@ir...> wrote: > Roman Yakovenko wrote: > > On 8/25/06, Neal Becker <ndb...@gm...> wrote: > >> Is there a way to add special functions/operators to a class? > >> > >> For example: > >> > >> struct X {}; > >> X& addAssign (X& x1, X const& x2) { return x1; } // silly example > >> > >> I want this to do: > >> .def ("__iadd__", addAssign, return_self<>()) > > > > I think that if you rename addAssign to __iadd__ this will work, but I > > am not sure. > > > > mb.free_function( 'addAssign' ).rename( '__iadd__' ) > > I think this would only work when addAssign() was a member of X. In this case it would work, because first argument of the function is X&. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Matthias B. <ba...@ir...> - 2006-08-25 18:00:26
|
Roman Yakovenko wrote: >> >> struct X {}; >> >> X& addAssign (X& x1, X const& x2) { return x1; } // silly example >> >> >> >> I want this to do: >> >> .def ("__iadd__", addAssign, return_self<>()) >> > >> > I think that if you rename addAssign to __iadd__ this will work, but I >> > am not sure. >> > >> > mb.free_function( 'addAssign' ).rename( '__iadd__' ) >> >> I think this would only work when addAssign() was a member of X. > > In this case it would work, because first argument of the function is X&. But in the generated Python bindings it would only be a global function called __iadd__ and not a method X.__iadd__. - Matthias - |
From: Roman Y. <rom...@gm...> - 2006-08-25 18:06:19
|
On 8/25/06, Matthias Baas <ba...@ir...> wrote: > But in the generated Python bindings it would only be a global function > called __iadd__ and not a method X.__iadd__. You are right. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Neal B. <ndb...@gm...> - 2006-08-25 18:10:10
|
On Friday 25 August 2006 1:06 pm, Matthias Baas wrote: > Roman Yakovenko wrote: > > On 8/25/06, Neal Becker <ndb...@gm...> wrote: > >> Is there a way to add special functions/operators to a class? > >> > >> For example: > >> > >> struct X {}; > >> X& addAssign (X& x1, X const& x2) { return x1; } // silly example > >> > >> I want this to do: > >> .def ("__iadd__", addAssign, return_self<>()) > > > > I think that if you rename addAssign to __iadd__ this will work, but I > > am not sure. > > > > mb.free_function( 'addAssign' ).rename( '__iadd__' ) > > I think this would only work when addAssign() was a member of X. > > I'm doing such things with the cdef() method of pypp_api which is > equivalent to adding a raw def() statement to the class (I just had to > name it something else because "def" is already a Python keyword). Usage > of cdef is almost identical to Boost.Python's def. The first argument is > the Python name, then comes the C/C++ function (as a string), followed > by optional policies, args and doc string in arbitrary order. In the > above example, it would look like this: > > root.Class("X").cdef("__iadd__", "addAssign", return_self()) > > (see https://realityforge.vrsource.org/view/PyppApi/Pypp_decorating) > Doesn't seem to work though, return_self isn't passed to generated code: mod = ModuleBuilder( headerFiles = "world.h", moduleName = "world" ) root = mod.parse() root.Class("World").expose() root.Class("X").expose() root.Function ("F1").expose() root.Class ("A").expose() root.Class ("B").expose() root.Class ("Z").expose() ##root.Function ("plusAssignOp").expose() root.Class("X").cdef("__iadd__", "addAssign", return_self()) mod.writeModule() generates: [...] bp::class_< X >( "X", bp::init< boost::shared_ptr<int> >(( bp::arg("_i") ))[bp::default_call_policies()] ) .def_readwrite( "i", &X::i ) .def( "__iadd__", addAssign ); <<< missing return_self() |
From: Matthias B. <ba...@ir...> - 2006-08-26 07:19:19
|
Neal Becker wrote: >> root.Class("X").cdef("__iadd__", "addAssign", return_self()) >> >> (see https://realityforge.vrsource.org/view/PyppApi/Pypp_decorating) >> > Doesn't seem to work though, return_self isn't passed to generated code: Oops, right, policies were ignored, I forgot that this was still on my todo list. I've just committed the fix (r470). - Matthias - |
From: Neal B. <ndb...@gm...> - 2006-08-28 12:30:16
|
On Friday 25 August 2006 1:06 pm, Matthias Baas wrote: > Roman Yakovenko wrote: > > On 8/25/06, Neal Becker <ndb...@gm...> wrote: > >> Is there a way to add special functions/operators to a class? > >> > >> For example: > >> > >> struct X {}; > >> X& addAssign (X& x1, X const& x2) { return x1; } // silly example > >> > >> I want this to do: > >> .def ("__iadd__", addAssign, return_self<>()) > > > > I think that if you rename addAssign to __iadd__ this will work, but I > > am not sure. > > > > mb.free_function( 'addAssign' ).rename( '__iadd__' ) > > I think this would only work when addAssign() was a member of X. > > I'm doing such things with the cdef() method of pypp_api which is > equivalent to adding a raw def() statement to the class (I just had to > name it something else because "def" is already a Python keyword). Usage > of cdef is almost identical to Boost.Python's def. The first argument is > the Python name, then comes the C/C++ function (as a string), followed > by optional policies, args and doc string in arbitrary order. In the > above example, it would look like this: > > root.Class("X").cdef("__iadd__", "addAssign", return_self()) > One of the really cool things about boost::python is that you can not only wrap c++ classes, but synthesize new functionality. Specifically, you can make python classes that don't have c++ equivalents, or add features to python classes that don't exist in the c++ class. We can indeed use cdef for this, but it's rather low level. I wonder if we can make a better api for this, maybe something like: add_method (...) |
From: Matthias B. <ba...@ir...> - 2006-08-28 13:10:14
|
Neal Becker wrote: >> root.Class("X").cdef("__iadd__", "addAssign", return_self()) > > One of the really cool things about boost::python is that you can not only > wrap c++ classes, but synthesize new functionality. Specifically, you can > make python classes that don't have c++ equivalents, or add features to > python classes that don't exist in the c++ class. > > We can indeed use cdef for this, but it's rather low level. I wonder if we > can make a better api for this, maybe something like: > > add_method (...) Can you elaborate on the '...'? (as this is the interesting part) How would you like the API to look like? - Matthias - |
From: Roman Y. <rom...@gm...> - 2006-08-28 12:45:22
|
On 8/28/06, Neal Becker <ndb...@gm...> wrote: > On Friday 25 August 2006 1:06 pm, Matthias Baas wrote: > > Roman Yakovenko wrote: > > > On 8/25/06, Neal Becker <ndb...@gm...> wrote: > > >> Is there a way to add special functions/operators to a class? > > >> > > >> For example: > > >> > > >> struct X {}; > > >> X& addAssign (X& x1, X const& x2) { return x1; } // silly example > > >> > > >> I want this to do: > > >> .def ("__iadd__", addAssign, return_self<>()) > > > > > > I think that if you rename addAssign to __iadd__ this will work, but I > > > am not sure. > > > > > > mb.free_function( 'addAssign' ).rename( '__iadd__' ) > > > > I think this would only work when addAssign() was a member of X. > > > > I'm doing such things with the cdef() method of pypp_api which is > > equivalent to adding a raw def() statement to the class (I just had to > > name it something else because "def" is already a Python keyword). Usage > > of cdef is almost identical to Boost.Python's def. The first argument is > > the Python name, then comes the C/C++ function (as a string), followed > > by optional policies, args and doc string in arbitrary order. In the > > above example, it would look like this: > > > > root.Class("X").cdef("__iadd__", "addAssign", return_self()) > > > > One of the really cool things about boost::python is that you can not only > wrap c++ classes, but synthesize new functionality. Specifically, you can > make python classes that don't have c++ equivalents, or add features to > python classes that don't exist in the c++ class. > > We can indeed use cdef for this, but it's rather low level. I wonder if we > can make a better api for this, maybe something like: > > add_method (...) You and Matthias are solving different problems. Matthias generates new function from the script and than adds it to the class. You already have function declaration, and the only thing you want to do is to associate it with the class. I think it will take only few hours to implement what you are asking for. cls = mb.class_("X") f = mb.free_function( "addAssign" ) cls.add_method( f ) While it is possible to implement this on top of cdef function, I think it will be a wrong solution. Why? Because next functionality already exists in code creators: 1. keyword arguments ( default values ) 2. introducing function type into generated code 3. argument policies ( they will not work on function ) 4. warnings 5. class held type and smart pointers registration -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Matthias B. <ba...@ir...> - 2006-08-28 13:16:12
|
Roman Yakovenko wrote: >> We can indeed use cdef for this, but it's rather low level. I wonder >> if we >> can make a better api for this, maybe something like: >> >> add_method (...) > > You and Matthias are solving different problems. > Matthias generates new function from the script and than adds it to the > class. Well, not only. In my Maya bindings I'm also doing the same thing as Neal, i.e. I have manually written C++ functions that I add as methods to some classes using cdef(). > You already have function declaration, and the only thing you want to > do is to associate it > with the class. I think it will take only few hours to implement what > you are asking for. > > cls = mb.class_("X") > f = mb.free_function( "addAssign" ) > cls.add_method( f ) I think this could be a useful feature, couldn't it? However, in my case I would have to change my project setup a bit as Py++ doesn't "see" my manually written functions. I'm not parsing my own headers so the query for the free function wouldn't work. > While it is possible to implement this on top of cdef function, I > think it will be a wrong > solution. Why? Because next functionality already exists in code creators: > 1. keyword arguments ( default values ) > 2. introducing function type into generated code > 3. argument policies ( they will not work on function ) > 4. warnings > 5. class held type and smart pointers registration But in the above example f is already a "real" declaration that will get turned into a "real" code creator, so all the above features could be used, couldn't they? - Matthias - |
From: Roman Y. <rom...@gm...> - 2006-08-28 13:22:42
|
On 8/28/06, Matthias Baas <ba...@ir...> wrote: > Roman Yakovenko wrote: > >> We can indeed use cdef for this, but it's rather low level. I wonder > >> if we > >> can make a better api for this, maybe something like: > >> > >> add_method (...) > > > > You and Matthias are solving different problems. > > Matthias generates new function from the script and than adds it to the > > class. > > Well, not only. In my Maya bindings I'm also doing the same thing as > Neal, i.e. I have manually written C++ functions that I add as methods > to some classes using cdef(). It does not different from what I say. You did not feed the declarations to Py++. > > You already have function declaration, and the only thing you want to > > do is to associate it > > with the class. I think it will take only few hours to implement what > > you are asking for. > > > > cls = mb.class_("X") > > f = mb.free_function( "addAssign" ) > > cls.add_method( f ) > > I think this could be a useful feature, couldn't it? Yes. > However, in my case I would have to change my project setup a bit as > Py++ doesn't "see" my manually written functions. I'm not parsing my own > headers so the query for the free function wouldn't work. > > > While it is possible to implement this on top of cdef function, I > > think it will be a wrong > > solution. Why? Because next functionality already exists in code creators: > > 1. keyword arguments ( default values ) > > 2. introducing function type into generated code > > 3. argument policies ( they will not work on function ) > > 4. warnings > > 5. class held type and smart pointers registration > > But in the above example f is already a "real" declaration that will get > turned into a "real" code creator, so all the above features could be > used, couldn't they? I just wanted to save time :-). I can implement the feature, but it will take some time. Do you want to try to implement it? -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Neal B. <ndb...@gm...> - 2006-08-29 15:59:33
|
On Monday 28 August 2006 9:22 am, Roman Yakovenko wrote: > On 8/28/06, Matthias Baas <ba...@ir...> wrote: > > Roman Yakovenko wrote: > > >> We can indeed use cdef for this, but it's rather low level. I wonder > > >> if we > > >> can make a better api for this, maybe something like: > > >> > > >> add_method (...) > > > > > > You and Matthias are solving different problems. > > > Matthias generates new function from the script and than adds it to the > > > class. > > > > Well, not only. In my Maya bindings I'm also doing the same thing as > > Neal, i.e. I have manually written C++ functions that I add as methods > > to some classes using cdef(). > > It does not different from what I say. You did not feed the > declarations to Py++. > > > > You already have function declaration, and the only thing you want to > > > do is to associate it > > > with the class. I think it will take only few hours to implement what > > > you are asking for. > > > > > > cls = mb.class_("X") > > > f = mb.free_function( "addAssign" ) > > > cls.add_method( f ) > > I don't understand all of what you guys said, but it sounds like this is what I had in mind. f = mb.free_function ("addAssign") what is "free_function"? Is this new or already existing? cls.add_method (f) sounds right. I guess need to be able to set some properties on it as well. Usual stuff. |
From: Matthias B. <ba...@ir...> - 2006-08-29 07:15:27
|
Roman Yakovenko wrote: >> But in the above example f is already a "real" declaration that will get >> turned into a "real" code creator, so all the above features could be >> used, couldn't they? > > I just wanted to save time :-). I can implement the feature, but it > will take some time. > Do you want to try to implement it? Well, currently I have no need for this feature for the Maya bindings (as I said, Py++ doesn't see my manually created functions so I would have to stick to cdef anyway (which doesn't impose any disadvantage for me yet)). Apart from that, I'd first love to hear Neal's opinion on what the API should look like anyway. (And I'm still busy with the arg policies...) - Matthias - |
From: Roman Y. <rom...@gm...> - 2006-08-29 07:19:35
|
On 8/29/06, Matthias Baas <ba...@ir...> wrote: > Roman Yakovenko wrote: > >> But in the above example f is already a "real" declaration that will get > >> turned into a "real" code creator, so all the above features could be > >> used, couldn't they? > > > > I just wanted to save time :-). I can implement the feature, but it > > will take some time. > > Do you want to try to implement it? > > Well, currently I have no need for this feature for the Maya bindings > (as I said, Py++ doesn't see my manually created functions so I would > have to stick to cdef anyway (which doesn't impose any disadvantage for > me yet)). > Apart from that, I'd first love to hear Neal's opinion on what the API > should look like anyway. Neal did we understand your use case right? > (And I'm still busy with the arg policies...) I hope in a few days we will join the efforts. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Matthias B. <ba...@ir...> - 2006-08-29 16:48:34
|
Neal Becker wrote: >>>> cls = mb.class_("X") >>>> f = mb.free_function( "addAssign" ) >>>> cls.add_method( f ) > > I don't understand all of what you guys said, but it sounds like this is what > I had in mind. > > f = mb.free_function ("addAssign") > > what is "free_function"? Is this new or already existing? It's the syntax of the Py++ high-level API, the pypp_api equivalent is the Function() method. So back to your initial example. Using the add_method approach you could write the following: f = root.Function("addAssign") f.rename("__iadd__") f.setPolicy(return_self()) root.Class("X").addMethod(f) Currently, you would have to write the following instead: root.Class("X").cdef("__iadd__", "addAssign", return_self()) Well, if *I* had to choose in this example, I would still use the latter option because of its brevity. Your goal has been to be less "low level" and get to a "better" API. But frankly, I don't see how the first option should have achieved these goals. But don't get me wrong, I don't say that add_method() is always a bad thing and cdef() is always better. There's merit in having something like add_method(), but probably not in this particular case (which was used as an example that a new API should improve). - Matthias - |
From: Roman Y. <rom...@gm...> - 2006-08-29 17:57:55
|
On 8/29/06, Matthias Baas <ba...@ir...> wrote: > Neal Becker wrote: > >>>> cls = mb.class_("X") > >>>> f = mb.free_function( "addAssign" ) > >>>> cls.add_method( f ) > > > > I don't understand all of what you guys said, but it sounds like this is what > > I had in mind. > > > > f = mb.free_function ("addAssign") > > > > what is "free_function"? Is this new or already existing? free_function returns a reference to free function declaration. It exists. > It's the syntax of the Py++ high-level API, the pypp_api equivalent is > the Function() method. > > So back to your initial example. Using the add_method approach you could > write the following: > > f = root.Function("addAssign") > f.rename("__iadd__") > f.setPolicy(return_self()) > root.Class("X").addMethod(f) > > Currently, you would have to write the following instead: > > root.Class("X").cdef("__iadd__", "addAssign", return_self()) > > > Well, if *I* had to choose in this example, I would still use the latter > option because of its brevity. Your goal has been to be less "low level" > and get to a "better" API. But frankly, I don't see how the first option > should have achieved these goals. In this specific case you are right. > But don't get me wrong, I don't say that add_method() is always a bad > thing and cdef() is always better. There's merit in having something > like add_method(), but probably not in this particular case (which was > used as an example that a new API should improve). Matthias, I think I still need this function, because it will improve few my scripts and I like the idea. Do you want to implement it? It could be a nice introduction to code creators factory. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |