List Info

Thread: Boost Python and ctypes




Boost Python and ctypes
country flaguser name
United States
2008-02-24 06:41:15
I am trying to bridge two libraries, one a C library bound
into python 
using ctypes, and the other a C++ library using Boost
Python.

In the C++ library, I have a class similar to the following,
with a 
member function that returns a pointer to an internal
buffer.

struct Test
{
float data[16];

float *get_data() {return data;}
}

I have wrapped this in a seeming logical way:

BOOST_MODULE(test) {
class_<Test>("Test")
.def("get_data", &Test::get_data,
return_value_policy< return_by_value >();
}

Which suffices to retrieve a "float *" instance
from Python. However, I 
need to pass this pointer to a ctypes-bound function:

void some_function(float *);

I can call this function from python without any trouble,
using a 
ctypes created buffer:

buffer = (c_float * 16)
some_function(buffer)

However, when I attempt to pass the result of get_data()
into this 
function, ctypes causes an error because Boost Python's
"float *" type 
does not match ctypes' POINTER(c_float) type. Equally,
ctypes' cast() 
function doesn't work to coerce the pointer type, because it
doesn't 
recognise the "float *" type either.

Does anyone have a workaround to coerce these types (which
each contain 
the same underlying pointer) together?

Thanks in advance for any suggestions,

- Tristam


_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

Re: Boost Python and ctypes
country flaguser name
United States
2008-02-26 13:34:24
I don't know how to integrate this into Boost.Python in a
clean way, but here 
is a litter terminal example that can help:

>>> array = (ctypes.c_int * 3)(1,2,3)
>>> addr = ctypes.addressof(array)
>>> arrayPtr = ctypes.cast(addr,
ctypes.POINTER((ctypes.c_int)))
>>> array[0]
1
>>> arrayPtr[0]
1

So basically if you can get a long value into python
representing the address 
of your float array you are good to go.  This is done in
Python-Ogre by just 
wrapping a manual cast function:

unsigned long castToAddress(float* ptr)
{
    return (unsigned long)ptr;
}

A more permanent way to do this would be to change your
wrapper to execute 
this code with Boost.Python's C++ python API interface (not
tested):

bp::object convertFloat(float* ptr)
{
    bp::object ctypes = bp::import("ctypes");

    bp::long addr((unsigned addr)ptr);
    bp::object
pointerType(ctypes["POINTER"](ctypes["c_float
"]));

    return ctypes["cast"](addr, pointerType);
}

I believe you can do this by specifying a manual to python
convert for the 
"float*" type.

Hope that helps,
Joseph Lisee

_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

Re: Boost Python and ctypes
user name
2008-02-26 14:49:41
Thank you for the prompt answer - that accomplishes exactly what I was trying to do!

I haven't had a lot of luck tracking down the hooks to add a manual conversion for 'float *' into the types registry, do you have any reference for that handy?

- Tristam

On 26/02/2008, Joseph Lisee < jliseegmail.com">jliseegmail.com> wrote:
I don't know how to integrate this into Boost.Python in a clean way, but here
is a litter terminal example that can help:

>>&gt; array = (ctypes.c_int * 3)(1,2,3)
>>&gt; addr = ctypes.addressof(array)
>>&gt; arrayPtr = ctypes.cast(addr, ctypes.POINTER((ctypes.c_int)))
>>&gt; array[0]
1
>>&gt; arrayPtr[0]
1

So basically if you can get a long value into python representing the address
of your float array you are good to go. &nbsp;This is done in Python-Ogre by just
wrapping a manual cast function:

unsigned long castToAddress(float* ptr)
{
 &nbsp; &nbsp;return (unsigned long)ptr;
}

A more permanent way to do this would be to change your wrapper to execute
this code with Boost.Python's C++ python API interface (not tested):

bp::object convertFloat(float* ptr)
{
 &nbsp; &nbsp;bp::object ctypes = bp::import("ctypes");

 &nbsp; &nbsp;bp::long addr((unsigned addr)ptr);
 &nbsp; &nbsp;bp::object pointerType(ctypes[&quot;POINTER"](ctypes["c_float";]));

 &nbsp; &nbsp;return ctypes[&quot;cast&quot;](addr, pointerType);
}

I believe you can do this by specifying a manual to python convert for the
"float*" type.

Hope that helps,
Joseph Lisee

_______________________________________________
C++-sig mailing list
C++-sigpython.org">C++-sigpython.org
http://mail.python.org/mailman/listinfo/c++-sig

 
Re: Boost Python and ctypes
country flaguser name
United States
2008-02-26 15:09:24
> Thank you for the prompt answer - that accomplishes
exactly what I was trying
to do!
> I haven't had a lot of luck tracking down the hooks to
add a manual conversion
for 'float *' into the types registry, do you have any
reference for that handy?
> 
> - Tristam

No problem, I think this is what you are looking for:
http://www.boost.org/libs/python/doc/v2/to_pytho
n_converter.html

-Joseph Lisee

_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

Re: Boost Python and ctypes
user name
2008-02-26 16:05:05
Now we are into the dizzying&nbsp;world of template error messages

So I have a class Matrix, which exposes a pointer to float, and a conversion operator to POINTER(c_float):

struct Matrix {
int test();
float *ptr();
};

struct ctypes_float_ptr
{
static PyObject *convert(float *ptr)
{
  object ctypes = import(&quot;ctypes&quot;);
 long_ addr((unsigned)ptr);
 object pointerType(ctypes[&quot;POINTER"](ctypes["c_float";]));
 return ctypes[&quot;cast&quot;](addr, pointerType).ptr();
}
};

BOOST_PYTHON_MODULE(math)
{
to_python_converter<float *, ctypes_float_ptr>();

class_&lt;Matrix>;("Matrix")
.def(&quot;test&quot;, &Matrix::test) // this compiles fine
.def(&quot;ptr&quot;, &Matrix::ptr) // error here
;
}

And the error is as follows:

src/math.cpp:146: error: no matching function for call to 'boost::python::class_<math::Matrix, boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::def(const char [4], <unknown type>)'

Any pointers on where to go from here?

On 26/02/2008, Joseph Lisee < jliseegmail.com">jliseegmail.com> wrote:
> Thank you for the prompt answer - that accomplishes exactly what I was trying
to do!
> I haven't had a lot of luck tracking down the hooks to add a manual conversion
for 'float *' into the types registry, do you have any reference for that handy?
>
> - Tristam


No problem, I think this is what you are looking for:
http://www.boost.org/libs/python/doc/v2/to_python_converter.html


-Joseph Lisee


_______________________________________________
C++-sig mailing list
C++-sigpython.org">C++-sigpython.org
http://mail.python.org/mailman/listinfo/c++-sig

 
[1-5]

about | contact  Other archives ( Real Estate discussion Medical topics )