Hello,

The topic below was opened in the Boost development mailing list,
where it's been pointed out to me that it fits better here.

You can also read the thread archive:
http://thread.gmane.org/gmane.comp.lib.boost.devel/186573

Regards
Bruno


---------- Forwarded message ----------


Hello,

I have written a little function that converts any Boost.Fusion
sequence into a Python tuple (boost::python::tuple). If a sub-sequence
is nested in the sequence, the result will also be a nested tuple (for
instance, boost::make_tuple(0, std::make_pair(1, 2), 3) will give (0,
(1, 2), 3) in Python).

The source code is attached to this mail.

The principle is that any sequence previously adapted to Boost.Fusion
will become a tuple in Python. So, by including the right
boost/fusion/adapted/xxx header, one can convert a pair, a tuple, a
boost::array, and obviously any of the sequences provided by
Boost.Fusion. For example:

#include <boost/python.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>
#include <boost/fusion/container/generation/make_vector.hpp>
#include "make_tuple_from_fusion_sequence.hpp"

using namespace boost::python;

tuple from_sequence()
{
   return make_tuple_from_fusion(
              boost::fusion::make_vector(
                 1,
                 std::make_pair("first", "second"),
                 2,
                 boost::make_tuple('a', 'b', 'c'),
                 3
              )
          );
}

BOOST_PYTHON_MODULE(mymodule)
{
   def("from_sequence", &from_sequence);
}


In Python we get:

>>> import mymodule
>>> mymodule.from_sequence()
(1, ('first', 'second'), 2, ('a', 'b', 'c'), 3)


Is there any interest in adding this function into Boost.Python? If
yes, I can write the doc and tests, clean the source and maybe improve
the implementation (for example, I feel that I could avoid the use of
m_iteration with a better use of Boost.Fusion...).


Regards
Bruno
#ifndef BOOST_PYTHON_MAKE_TUPLE_FROM_FUSION_H_
#define BOOST_PYTHON_MAKE_TUPLE_FROM_FUSION_H_


#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/python/tuple.hpp>


namespace boost {
namespace python {


class tuple_maker
{
public:
    tuple_maker(tuple& t):
    m_tuple(t),
    m_iteration(0)
    {}

    template <class T>
    typename disable_if<fusion::traits::is_sequence<T>, void>::type
    operator() (const T& element) const
    { add_element(element); }

    template <class Sequence>
    typename enable_if<fusion::traits::is_sequence<Sequence>, void>::type
    operator() (const Sequence& s) const
    { add_element(make_tuple_from_fusion(s)); }

private:
    template <class T>
    void add_element(const T& element) const
    {
        PyTuple_SET_ITEM(
            m_tuple.ptr(),
            m_iteration++,
            incref(object(element).ptr())
        );
    }

    tuple& m_tuple;
    mutable int m_iteration;
};


template <class Sequence>
tuple make_tuple_from_fusion(const Sequence& s)
{
    tuple result((detail::new_reference)::PyTuple_New(fusion::size(s)));
    fusion::for_each(s, tuple_maker(result));
    return result;
}


} // namespace python
} // namespace boost


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

Reply via email to