[C++-sig] Calling python from c++ with tuple and dict args.

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

[C++-sig] Calling python from c++ with tuple and dict args.

Alex Mohr-2
Hi folks,

I have a python callable object in C++ (call it 'f') and a tuple and
dict of arguments (call them 't' and 'd').  In python, I could call f
like this:

f(*t, **d)

Is there a convenient boost python way to call the python object f like
this from C++?

Thanks,

Alex
_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

Markus Plessing
> Hi folks,

Hi Alex,

> [...]
> Is there a convenient boost python way to call the python object f like
> this from C++?

This may help. If not take a look at [1]

------------------------------------------------------------------------
PyObject* PyObject_CallObject
        (PyObject *callable_object, PyObject *args)

    Return value: New reference.

Call a callable Python object callable_object, with arguments given
by the tuple args. If no arguments are needed, then args may be NULL.
Returns the result of the call on success, or NULL on failure. This is
the equivalent of the Python expression "apply(callable_object, args)"
or "callable_object(*args)".
-------------------------------------------------------------------------

> Thanks,
>
> Alex

Kind regards,

Markus

[1] http://docs.python.org/api/object.html#l2h-241

--
--------------------------------------------------------
EMS Dr. Thomas Wuensche
Sonnenhang 3
85304 Ilmmuenster, Germany
Phone: +49-8441-490260
Fax:   +49-8441-81860
email: [hidden email]
Web http://www.ems-wuensche.com (.de)
--------------------------------------------------------

_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

Alex Mohr-2
Thanks Markus,

I was planning to use PyObject_Call which takes a tuple and a dict if I
couldn't find a nice boost python way to do it.

It seems like it would be possible to do something like this:

bp::object::operator()(bp::unpacked_tuple const &args,
                        bp::unpacked_dict const &kw) {
     // call as self(*args, **kw)
}

And then define unary * operators for tuple and dict so that *tuple
would produce an unpacked_tuple and **dict would produce an unpacked_dict.

Alex


Markus Plessing wrote:

>>Hi folks,
>
>
> Hi Alex,
>
>
>>[...]
>>Is there a convenient boost python way to call the python object f like
>>this from C++?
>
>
> This may help. If not take a look at [1]
>
> ------------------------------------------------------------------------
> PyObject* PyObject_CallObject
> (PyObject *callable_object, PyObject *args)
>
>     Return value: New reference.
>
> Call a callable Python object callable_object, with arguments given
> by the tuple args. If no arguments are needed, then args may be NULL.
> Returns the result of the call on success, or NULL on failure. This is
> the equivalent of the Python expression "apply(callable_object, args)"
> or "callable_object(*args)".
> -------------------------------------------------------------------------
>
>
>>Thanks,
>>
>>Alex
>
>
> Kind regards,
>
> Markus
>
> [1] http://docs.python.org/api/object.html#l2h-241
>
_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

David Abrahams
Alex Mohr <[hidden email]> writes:

> Thanks Markus,
>
> I was planning to use PyObject_Call which takes a tuple and a dict if I
> couldn't find a nice boost python way to do it.
>
> It seems like it would be possible to do something like this:
>
> bp::object::operator()(bp::unpacked_tuple const &args,
>                         bp::unpacked_dict const &kw) {
>      // call as self(*args, **kw)
> }
>
> And then define unary * operators for tuple and dict so that *tuple
> would produce an unpacked_tuple and **dict would produce an unpacked_dict.
>
> Alex

That's ******* E V I L *****  !!!

and I love it!  Post a patch including tests and I'll check it in.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

Nat Goodspeed
In reply to this post by Alex Mohr-2
> -----Original Message-----
> From: [hidden email] [mailto:[hidden email]]
On
> Behalf Of David Abrahams
> Sent: Tuesday, March 07, 2006 2:26 PM
> To: [hidden email]
> Subject: Re: [C++-sig] Calling python from c++ with tuple and dict
args.

>
> > It seems like it would be possible to do something like this:
> >
> > bp::object::operator()(bp::unpacked_tuple const &args,
> >                         bp::unpacked_dict const &kw) {
> >      // call as self(*args, **kw)
> > }
> >
> > And then define unary * operators for tuple and dict so that *tuple
> > would produce an unpacked_tuple and **dict would produce an
> unpacked_dict.

[Nat] I find myself wondering what *dict should produce -- an error?
_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

Alex Mohr-2
> [Nat] I find myself wondering what *dict should produce -- an error?

It's a good question.  I think it should be an error, but I'm not sure
how it should manifest itself.  *dict needs to produce a valid object
(so we can invoke * on it), but that object will have an API that will
likely not really work anywhere other than where it is meant to, and we
can provide overloads for the places where we expect it might
accidentally be used.  For instance:

bp::object::operator()(unpacked_tuple const &,
     /* result of *dict */ intermediate_unpacked_dict const &) {

    // compile-time-error
}

Incidentally, the same general idea is true about unpacked_tuple and
unpacked_dict -- we need to try to make sure that they only make sense
in only the case of the specific operator() on object.

Alex
_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

Alex Mohr-2
In reply to this post by David Abrahams
> That's ******* E V I L *****  !!!
>
> and I love it!  Post a patch including tests and I'll check it in.

Cool -- I'll try to do it in my spare time. :)

Alex
_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

David Abrahams
In reply to this post by Nat Goodspeed
"Nat Goodspeed" <[hidden email]> writes:

>> -----Original Message-----
>> From: [hidden email] [mailto:[hidden email]]
> On
>> Behalf Of David Abrahams
>> Sent: Tuesday, March 07, 2006 2:26 PM
>> To: [hidden email]
>> Subject: Re: [C++-sig] Calling python from c++ with tuple and dict
> args.
>>
>> > It seems like it would be possible to do something like this:
>> >
>> > bp::object::operator()(bp::unpacked_tuple const &args,
>> >                         bp::unpacked_dict const &kw) {
>> >      // call as self(*args, **kw)
>> > }
>> >
>> > And then define unary * operators for tuple and dict so that *tuple
>> > would produce an unpacked_tuple and **dict would produce an
>> unpacked_dict.
>
> [Nat] I find myself wondering what *dict should produce -- an error?

Clearly not.  You can't get to **dict without *dict.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

David Abrahams
In reply to this post by David Abrahams
David Abrahams <[hidden email]> writes:

> Alex Mohr <[hidden email]> writes:
>
>> Thanks Markus,
>>
>> I was planning to use PyObject_Call which takes a tuple and a dict if I
>> couldn't find a nice boost python way to do it.
>>
>> It seems like it would be possible to do something like this:
>>
>> bp::object::operator()(bp::unpacked_tuple const &args,
>>                         bp::unpacked_dict const &kw) {
>>      // call as self(*args, **kw)
>> }
>>
>> And then define unary * operators for tuple and dict so that *tuple
>> would produce an unpacked_tuple and **dict would produce an unpacked_dict.
>>
>> Alex
>
> That's ******* E V I L *****  !!!
>
> and I love it!  Post a patch including tests and I'll check it in.

Huh, it looks like we should really extend all the overloads on object
so you can do:

   o(1, 2, 3, *t, **d)

That might be a touch more complex.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

Alex Mohr-2
> Huh, it looks like we should really extend all the overloads on object
> so you can do:
>
>    o(1, 2, 3, *t, **d)
>
> That might be a touch more complex.

You're right.  Looks like we need to support:
o(A1..N)
o(A1..N, unpacked_tuple_args)
o(A1..N, unpacked_tuple_args, unpacked_dict_args)

My intuition says that we can just add the extra two along with each
instance of operator().  So in object_core.hpp it'd be:

object operator()() const;
object operator()(unpacked_tuple const &) const;
object operator()(unpacked_tuple const &, unpacked_dict const &) const;

And then in the iterated object_call.hpp, we'd add the two other
versions (tuple and tuple + dict) to provide the multi-leading arg
versions (stuff along these lines):

template <BOOST_PP_ENUM_PARAMS_Z(1, N, class A)>
typename detail::dependent<object, A0>::type
operator()(BOOST_PP_ENUM_BINARY_PARAMS(1, N, A, const &a),
     unpacked_tuple const &args, unpacked_dict const &kw) const

Then we would modify bp::call<> similarly to accept trailing unpacked
tuples and dicts, and call through to python with the combined arguments.

Anything seem out-of-line here?  If not, I'm willing to try it.  Seems
plausible.

Alex
_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

David Abrahams
Alex Mohr <[hidden email]> writes:

>> Huh, it looks like we should really extend all the overloads on object
>> so you can do:
>>
>>    o(1, 2, 3, *t, **d)
>>
>> That might be a touch more complex.
>
> You're right.  Looks like we need to support:
> o(A1..N)
> o(A1..N, unpacked_tuple_args)
> o(A1..N, unpacked_tuple_args, unpacked_dict_args)

not

   o(A1..N, unpacked_dict_args)

as well?

> My intuition says that we can just add the extra two along with each
> instance of operator().  So in object_core.hpp it'd be:
>
> object operator()() const;
> object operator()(unpacked_tuple const &) const;
> object operator()(unpacked_tuple const &, unpacked_dict const &) const;

That won't work with the old broken compilers (vc6/7), I think, which
-- at least for now -- are still supported.  But I think it's pretty
easy to do something inside boost/python/call.hpp to make it recognize
the unpacked tuple and dict arguments and treat them specially.

> And then in the iterated object_call.hpp, we'd add the two other
> versions (tuple and tuple + dict) to provide the multi-leading arg
> versions (stuff along these lines):
>
> template <BOOST_PP_ENUM_PARAMS_Z(1, N, class A)>
> typename detail::dependent<object, A0>::type
> operator()(BOOST_PP_ENUM_BINARY_PARAMS(1, N, A, const &a),
>      unpacked_tuple const &args, unpacked_dict const &kw) const
>
> Then we would modify bp::call<> similarly to accept trailing unpacked
> tuples and dicts, and call through to python with the combined arguments.

If you just modify boost::python::call<> you don't need to touch
anything else.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

Alex Mohr-2
> not
>
>    o(A1..N, unpacked_dict_args)
>
> as well?

Yes -- that too, and that's what I've implemented.

> That won't work with the old broken compilers (vc6/7), I think, which
> -- at least for now -- are still supported.  But I think it's pretty
> easy to do something inside boost/python/call.hpp to make it recognize
> the unpacked tuple and dict arguments and treat them specially.

Interesting.  The only environments I have readily available are gcc 4+
on linux and vc-8_0 on Windows and the obvious thing seems to work on
those.  So I'll likely need some help with supporting the older
compilers.  Or -- is there an existing pattern somewhere that I can look at?

> If you just modify boost::python::call<> you don't need to touch
> anything else.

That's true -- I'll do that.  There is the question of whether
unpacked_tuple and unpacked_dict should count against MAX_ARITY though.
  That is, is MAX_ARITY the max number of explicit positional args, or
is MAX_ARITY the max number of c++ args?

What is the preferred way of generating a patch to post to the list?

Thanks,

Alex
_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

Neal Becker
Alex Mohr wrote:

>> not
>>
>>    o(A1..N, unpacked_dict_args)
>>
>> as well?
>
> Yes -- that too, and that's what I've implemented.
>
>> That won't work with the old broken compilers (vc6/7), I think, which
>> -- at least for now -- are still supported.  But I think it's pretty
>> easy to do something inside boost/python/call.hpp to make it recognize
>> the unpacked tuple and dict arguments and treat them specially.
>
> Interesting.  The only environments I have readily available are gcc 4+
> on linux and vc-8_0 on Windows and the obvious thing seems to work on
> those.  So I'll likely need some help with supporting the older
> compilers.  Or -- is there an existing pattern somewhere that I can look
> at?
>
>> If you just modify boost::python::call<> you don't need to touch
>> anything else.
>
> That's true -- I'll do that.  There is the question of whether
> unpacked_tuple and unpacked_dict should count against MAX_ARITY though.
>   That is, is MAX_ARITY the max number of explicit positional args, or
> is MAX_ARITY the max number of c++ args?
>
> What is the preferred way of generating a patch to post to the list?
>

Diff? :)

_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

Alex Mohr-2
> Diff? :)

Heh, yeah, certainly -- I was wondering if there was a more formalized
set of steps, including particular diff args, preferred packaging and
compression, handling added files, etc.

Alex
_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] Calling python from c++ with tuple and dict args.

David Abrahams
In reply to this post by Alex Mohr-2
Alex Mohr <[hidden email]> writes:

>> not
>>
>>    o(A1..N, unpacked_dict_args)
>>
>> as well?
>
> Yes -- that too, and that's what I've implemented.
>
>> That won't work with the old broken compilers (vc6/7), I think, which
>> -- at least for now -- are still supported.  But I think it's pretty
>> easy to do something inside boost/python/call.hpp to make it recognize
>> the unpacked tuple and dict arguments and treat them specially.
>
> Interesting.  The only environments I have readily available are gcc 4+
> on linux and vc-8_0 on Windows and the obvious thing seems to work on
> those.  So I'll likely need some help with supporting the older
> compilers.  Or -- is there an existing pattern somewhere that I can look at?

Just don't rely on partial ordering or partial specialization.  Detect
the special types inside of each call<> overload using type traits and
handle them appropriately using some kind of metaprogramming.

>> If you just modify boost::python::call<> you don't need to touch
>> anything else.
>
> That's true -- I'll do that.  There is the question of whether
> unpacked_tuple and unpacked_dict should count against MAX_ARITY though.
>   That is, is MAX_ARITY the max number of explicit positional args, or
> is MAX_ARITY the max number of c++ args?

Make it the latter; it will be simpler.

> What is the preferred way of generating a patch to post to the list?

_enclose_ (rather than paste) a unified diff into a post.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig