from-python converter for aligned class

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

from-python converter for aligned class

Václav Šmilauer
I wrote a custom to-python converter for an aligned struct (It is a
128-bit aligned vector type from the http://eigen.tuxfamily.org 
library). I followed
http://www.boost.org/doc/libs/1_39_0/libs/python/doc/v2/faq.html#custom_string),
the converter looks like this:

     class AlignedType{ /*... */} __attribute__((aligned(16)));
     struct converter{
        converter(){
py::converter::registry::push_back(&convertible,&construct,py::type_id<AlignedType>());
        static void* convertible(PyObject* obj_ptr){ /*...*/ }
        static void construct(PyObject* obj_ptr,
py::converter::rvalue_from_python_stage1_data* data){
           void*
storage=((py::converter::rvalue_from_python_storage<VT>*)(data))->storage.bytes;
           // !! this creates AlignedType instance at a possibly
unaligned address !!
           new (storage) AlignedType;
           data->convertible=storage;
        }
     };

I am getting crashes due to mis-alignment of the resulting object,
because it is created at a possible unaligned address. Is there a way
around this? Can I allocate another chunk of memory, or enforce the
alignment before it is allocated?

Best regards, Vaclav


_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Reply | Threaded
Open this post in threaded view
|

Re: from-python converter for aligned class

Jim Bosch-2
On 02/12/2012 12:49 PM, Václav Šmilauer wrote:

> I wrote a custom to-python converter for an aligned struct (It is a
> 128-bit aligned vector type from the http://eigen.tuxfamily.org
> library). I followed
> http://www.boost.org/doc/libs/1_39_0/libs/python/doc/v2/faq.html#custom_string),
> the converter looks like this:
>
> class AlignedType{ /*... */} __attribute__((aligned(16)));
> struct converter{
> converter(){
> py::converter::registry::push_back(&convertible,&construct,py::type_id<AlignedType>());
>
> static void* convertible(PyObject* obj_ptr){ /*...*/ }
> static void construct(PyObject* obj_ptr,
> py::converter::rvalue_from_python_stage1_data* data){
> void*
> storage=((py::converter::rvalue_from_python_storage<VT>*)(data))->storage.bytes;
>
> // !! this creates AlignedType instance at a possibly unaligned address !!
> new (storage) AlignedType;
> data->convertible=storage;
> }
> };
>
> I am getting crashes due to mis-alignment of the resulting object,
> because it is created at a possible unaligned address. Is there a way
> around this? Can I allocate another chunk of memory, or enforce the
> alignment before it is allocated?
>

Hmm.  You might be able to make this work with another class that holds
the AlignedType and has an implicit conversion to it:

struct AlignedHolder {

     operator AlignedType const & () const {
         return *p;
     }

     std::auto_ptr<AlignedType> p;
};

You'd then write an rvalue converter for AlignedHolder, but register it
with type_id<AlignedType>().  Boost.Python will see the type_id for
AlignedType and try to use it when you have an "AlignedType const &"
argument, but it will try to pass the AlignedHolder object to your
function...at which point the implicit conversion will kick in.

I haven't tested this, and it involves really tricking Boost.Python, but
I think it might work.

Jim
_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Reply | Threaded
Open this post in threaded view
|

Re: constructing aligned instance in python

Václav Šmilauer
> Hmm.  You might be able to make this work with another class that holds
> the AlignedType and has an implicit conversion to it:

Nice trick, it surprisingly compiled.

I found meanwhile though that the problem is more general: whenever a new
instance of AlignedType is created from python, it will be possibly mis-aligned,
because the Python allocator does not care about alignment: it simply provides a
chunk of memory based on PyTypeObject.{tp_basicsize,tp_itemsize} for the type
being instantiated.

A possible workaround (though quite laborious) is to use the overloaded
operator new ot AlignedType, which aligns properly, and write all ctors
of the wrapped class such that pointer (manage_new_object, I assume?)
is returned:

  namespace py=boost::python;
  static AlignedType* AlignedType_new(){ return new AlignedType; }
  static AlignedType* AlignedType_copy(const AlignedType& other){
    return new AlignedType(other);
  }
  py::class_<AlignedType>("AlignedType",boost::python::no_init)
     .def("__init__",&AlignedType_new)
     .def("__init__",&AlignedType_copy)
  ;

Isn't that insane? Is there a better way?

Cheers, v.

_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig