ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> cpp-sig
cpp-sig
[C++-sig] function types as user-defined converters
by Troy D. Straszheim other posts by this author
Nov 6 2009 11:53AM messages near this date
Re: [C++-sig] [python] python + phoenix | Re: [C++-sig] [python] python + phoenix
> > I'm wondering if there isn't motivation here to cleanly integrate a
> > general facility for additional c++-side type conversions. 


I got distracted with boost.cmake stuff for a while but just got some
things working.  Simple example:

//  type hidden from python
struct Hidden
{
   double value;
};

//
//  c++ interface that uses hidden type
//
std::string takes_hidden(Hidden h)
{
   return std::string("Got an Hidden containing ")
     + boost::lexical_cast<std::string> (h.value);
}

//
//  converter object
//
struct dbl_to_Hidden
{
   typedef Hidden result_type;

   result_type operator()(double v) const
   {
     Hidden h;
     h.value = v;
     return a;
   }
};

// the module
BOOST_PYTHON_MODULE(udconversions_ext)
{
   def("takes_hidden",
     as<std::string(dbl_to_Hidden(double))> (&takes_hidden));
}                  ^^^^^^^^^^^^^^^^^^^^^

And the python:

 > >> from udconversions_ext import *
 > >> takes_a(13)
'Got an A containing 13'


Here's another contrived example:


// Here we have a class that takes optional<int>  arguments that
// python ought not know about:

struct S
{
   void set(optional<int>  v)
   {
     i = v;
   }
   void add(boost::optional<int>  oi)
   {
     if (i && oi)
       (*i) += (*oi);
   }
   std::string show()
   {
     if (i)
       return boost::lexical_cast<std::string> (*i);
     else
       return "<unset> ";
   }
   optional<int>  i;
};

// And a converter function object that converts a python::object
// to an optional<T>  (holding a T) if the object is
// convertible to T, otherwise it returns an empty optional<T> :

template <typename T> 
struct to_optional
{
   typedef optional<T>  result_type;

   result_type operator()(const bp::object& o)
   {
     bp::extract<T>  ex(o);
     if (ex.check())
       return optional<T> (ex());
     else
       return optional<T> ();
   }
};


BOOST_PYTHON_MODULE(opt_ext)
{

   bp::class_<S> ("S")
     .def("set", bp::as<void(S*, to_optional<int> (bp::object))>(&S::set))
     .def("add", bp::as<void(S*, to_optional<int> (bp::object))>(&S::add))
     .def("show", &S::show)      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     ;
};

And the result:

 > >> from opt_ext import *
 > >> s = S()
 > >> s.set(13)
 > >> s.show()
'13'
 > >> s.set(None)
 > >> s.show()
'<unset> '
 > >> s.set(None)
 > >> s.add(13)
 > >> s.show()
'<unset> '
 > >> s.set(13)
 > >> s.add(13)
 > >> s.show()
'26'

There are plenty of issues yet.

Currently, the converter type still leaks out to python in the signature:

     class S(Boost.Python.instance)
      |  add(...)
      |      add( (S)arg1, (object)arg2) ->  None :
      |
      |          C++ signature :
      |              void add(S*,to_optional<int>  
(*)(boost::python::api::object))


converters won't nest:

   def("foo", as<returnvalue(arg1, conv1(conv2(arg2)))> (&somefn)); // nah

I dont have a mechanism for hooking a user defined converter into the
*return* type.  I'm going to have to think about that one a bit more.
specifying a function type, whose return value is a pointer to a
function, is kinda nasty anyway:

   def("foo", as<(converter(*)(int))(bool, converter(float))> (&fn));

I'm just not sure it gets one anything other than terseness.  Maybe
a special return value policy is in order.

Also, there isn't a way to use an object's constructor as a converter,
That is, I'd like to support this syntax:

struct X {
   X(double);
};

void takes_X(X x);

def("takes_x", as<void(X(double))> (&takes_x));

But I think this involves adding some scaffolding so that
boost.python can differentiate between what in proto-ese is a Callable
Transform (what now works) and an Object Transform (convert
via constructor).

-t

_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@[...].org
http://mail.python.org/mailman/listinfo/cplusplus-sig
Thread:
Ravi
Troy D. Straszheim
Ravi
Troy D. Straszheim
Ravi
Troy D. Straszheim
Ravi
Troy D. Straszheim
Ravi
Lists Ravi
Troy D. Straszheim
Troy D. Straszheim

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved