boost::python, returning new PyObject references
David Abrahams
david.abrahams at rcn.com
Mon Jan 7 21:15:18 CET 2002
----- Original Message -----
From: "Arnaldur Gylfason" <arnaldur at decode.is>
> Dave,
>
> It would be great if you could give an example (maybe something that can
> solve object<sequence,mapping>) so I can see the way.
I don't think we're ready to solve that problem yet, but let me try to
sketch an approach (just a sketch, keep that in mind):
1. Low-level interface components are supplied by type generators
corresponding to fine-grained interface elements. Their constructor contains
the validation code:
struct getattr_generator
{
template <class T, Base = empty>
struct type : Base
{
void validate()
{
T* self = static_cast<T*>(this);
if (!self->ob_type->tp_getattr && !self->ob_type->tp_getattro)
throw something;
}
// maybe this should return object<>, I don't know.
ref getattr(char const* name)
{
T* self = static_cast<T*>(this);
return ref(PyObject_GetAttrString(self->get_callback()(),
name));
}
};
};
struct indexable_generator
{
template <class T, Base = empty>
struct type : Base
{
// select the right proxy type
typedef typename boost::mpl::select_type<
is_mutable<T>::value
, mutable_proxy
, const_proxy>::type proxy;
// implement operator[] for T
template <class U>
proxy operator[](U const& index_)
{
ref index(to_python(index_));
T* self = static_cast<T*>(this);
return proxy(some_expression(self->get_callback(),
self->set_callback(), ref));
}
void validate()
{
T* self = static_cast<T*>(this);
if
(!self->get_callback()()->ob_type->tp_as_sequence->tp_getitem)
throw something;
}
};
};
Concepts such as sequence may correspond to a type_list of these generators.
In the case of sequence, I don't think there's anything more than indexable:
struct sequence : mpl::type_list<indexable_generator> {};
struct integral :
mpl::type_list<addable_generator,subtractable_generator,...> {};
then we can define object<c1,c2,c3...cn> as:
template <class....>
struct object
: gen_linear_hierarchy<
typename get_unique_generators<mpl::type_list<c1,c2...cn> >::type
, use_generator<
object<c1,c2,c3...cn>
>
>
{
};
where use_generator is something like:
template <class Object>
struct use_generator
{
template <class Generator, class Base>
struct apply
{
typedef Generator::template type<Object, Base> type;
};
};
and where get_unique_generators is something like:
struct all_generators : mpl::type_list<
indexable_generator,getattr_generator, setattr_generator...>
{};
template <class ConceptList>
struct get_unique_generators
{
typedef typename mpl::copy_if<all_generators, in_a_sublist<ConceptList>
>::type type;
};
and in_a_sublist is:
template <class ListOfLists>
struct in_a_sublist
{
template <class T>
struct apply
{
BOOST_STATIC_CONSTANT(bool, value =
// an expression which is true iff T is in any
// of the Lists contained in ListOfLists
};
};
Whew, I'm tired now! This is pretty complicated; Perhaps it can be
simplified.
> I have only taken a brief look at 2 files in boost::mpl but am interested
> in exploring this kind of programming.
It's a lot of fun. Take a look at the example and test directories also for
some illuminating samples.
More information about the Cplusplus-sig
mailing list