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/
|