Ravi wrote:
>
> I'd rather have something along the lines of
>       .def< mpl::vector<void,T*,double> >("f1",f1)

I have something working.  There is still a bunch of stuff to iron out
yet.  I went with

  def("name", as<Signature>(callable));

where Signature is the signature with which callable will be called,
e.g.

  struct times_seven
  {
    template <typename T> struct result;

    template <typename Self, typename T>
    struct result<Self(T&)>  // annoying: reference
    {
      typedef T type;
    };

    template <typename T>
    T operator()(const T& t)
    {
      return t * 7;
    }
  };

  BOOST_PYTHON_MODULE( function_objects3_ext )
  {
    def("times_seven", as<int(int)>(times_seven()));
  }

the T& in the struct result is something I haven't yet sorted out, has
something to do with how I am constructing fusion sequences from the
converted python objects before calling fusion::invoke.  Anyhow, it
works:

  >>> times_seven(7)
  49

I thought that one might try to remove the necessity of having the
return type in the Signature and/or implementing the result_of
protocol, but maybe it is nice that they don't have to match:

  def("times_seven", as<double(int)>(times_seven()));

  >>> times_seven(7)
  49.0

boost::function still works, and doesn't require as<>:

  boost::function<int(int, int)> myplus = std::plus<int>();
  def("myplus", myplus);

and old-school function objects:

  def("otherplus", std::plus<int>())

I was surprised to find that it all plays nice with boost::phoenix:

  def("plus", as<int(int, int)>(arg1 + arg2));

  def("throw_if_gt_5",
      as<void(int)>(if_(arg1 > 5)
                    [ throw_(std::runtime_error("too big!!")) ]
                    .else_
                    [ std::cout << val("okay")                ]));

And boost::phoenix plays nice with shared_ptr, which plays nice with
boost::python:

  struct X { int x; };   typedef boost::shared_ptr<X> XPtr;

  class_<X, XPtr>("X")
    .def_readwrite("x", &X::x)
    .def("add7", as<void(X*)>  (arg1->*&X::x      += 7))
    .def("add8", as<void(XPtr)>(arg1->*&X::x      += 8))
    .def("add9", as<void(X&)>  (bind(&X::x, arg1) += 9))
  ;

the other little thing is overload resolution, for which I propose a
little helper function "unload" (underload? deload? resolve?  I dunno):

  void foo(int);
  void foo(double);

  def("foo", unload<void(int)>(foo));

Which is safer than

  def("foo", (void(*)(int)) foo);

and just as safe as, and less verbose than

  void(*fooint)(int) = foo;
  def("foo", fooint);

So that's where I'm at...  what do you make of that interface?

-t

_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to