Ravi wrote:
On Sunday 11 October 2009 19:44:29 troy d. straszheim wrote:
Why is the overloaded get_signature not picked up when it is declared
after the inclusion of the headers?
I'm not sure why it isn't picked up.
Does that mean that you can reproduce the problem I pointed out?
Yes I can.
I've been working in this area,
replacing most of detail/caller.hpp and detail/invoke.hpp with
boost.fusion, seen here:
http://gitorious.org/~straszheim/boost/straszheim/blobs/python/boost/python
/detail/caller.hpp
In the process, I overhauled get_signature to use boost::function_types,
and to be a metafunction, not a function:
http://gitorious.org/~straszheim/boost/straszheim/blobs/python/boost/python
/signature.hpp
IMHO, this is the right way to do it. This avoids relying on the compiler to
optimize out all the ugly tag-dispatching. Of course, Dave A & Ralf WGK did
not have function types when they wrote this originally.
Yes, the code was all dated ~2002. There are more corners of the code
that could use modernization as well.
[snip]
boost::function<int(X*, int)> bf0(fobj);
Why do you need to use boost::function here? Shouldn't the type be deduced
automatically?
Note that the .def() of the various boost::function objects work without
requiring the user to specialize get_signature, (since this modified
get_signature metafunction knows about boost::function objects). Here's
a different (working) example:
#include <boost/function.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/python.hpp>
#include <boost/python/class.hpp>
#include <boost/python/module.hpp>
struct X { int y; };
struct add_to
{
template <typename T>
T operator()(X* x, T t) const
{
return t + x->y;
}
std::string operator()(X* x, std::string s)
{
return s + boost::lexical_cast<std::string>(x->y);
}
};
using namespace boost::python;
BOOST_PYTHON_MODULE( function_objects_ext )
{
add_to add_to_inst;
boost::function<int(X*, int)> f_int(add_to_inst);
boost::function<std::string(X*, std::string)> f_string(add_to_inst);
boost::python::class_<X>( "X" )
.def_readwrite( "y", &X::y )
.def( "add_to", f_int)
.def( "add_to", f_string)
;
}
>>> from function_objects_ext import *
>>> x = X()
>>> x.y = 13
>>> x.add_to(1)
14
>>> x.add_to("foo")
'foo13'
Some musings:
I think interoperability with boost::function is a Good Thing, but in
the example above (and the previous), all it does is give def() a way to
tell what the signature of the function object is at compile time, and
it does so at a runtime cost. A specialization of get_signature works,
but strikes me as kinda ugly (it should at least be moved out of
'detail' if it is a user customization point). How about something like
class_<T>("T")
.def("f1", f1, sig<void(T*, double)>)
.def<void(T*, double)>("fi", f1)
Which looks pretty straightforward when dealing with function objects,
but when dealing with overloads, things get tricky:
void f2(T*, int);
void f2(T*, double);
class_<T>("T")
.def("f2", f2) // #1 error
.def("f2", (void(*)(T*, int))f2) // #2 ok but ugly
.def<void(T*, int)>("f2", f2) // #3 works but tricky
;
#1 is an error, because f2's type is undetermined.
#2 is how you can fix #1 in current practice (or with an alias).
#3 could work (I've tried, it works) if def, when passed a function
type, only accepts pointers to functions of that type, so that the
overload is resolved. But how to use this same form to also specify the
types of arbitrary function objects... haven't thought about that yet.
I'm fairly new to the internals of boost.python, and only just now got
this working... Do you see problems with this, specifically the
conversion of get_signature from function to metafunction?
I don't see any problems with the conversion of get_signature to a
metafunction. Do compile times get any longer?
I haven't checked this yet. I have other concerns re typechecking and
automatic conversions... I'll go back and look more closely.
-t
_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig