Discussion:
[C++-sig] Extracting base object reference of arbitrary Python object
Jeremy Murphy
2015-08-18 08:38:05 UTC
Permalink
Hi everyone,

I have what I assume is a fairly basic or naive question, but I'm still
quite new to Boost.Python so after scouring the documentation fruitlessly I
need to turn to community wisdom.

The short version of my question is: how do I access Python Shapely
geometry in C++ using Boost.Python?

I have written an algorithm in C++ using Boost.Geometry that I wish to
export for use in Python with Shapely geometry.
Ideally, I don't want to impose any new programming overhead on the Python
side, so I wish for this algorithm to 'just work' with Shapely geometry by
using the adaptor facilities in Boost.Geometry.

Being a bit naive, what I have done so far is to create some 'proxy' C++
classes to stand for Shapely classes, e.g.:

struct Point : public boost::python::object {}
struct LinearRing : public boost::python::object {}

which I can then adapt by specializing the required traits class templates.
My algorithm in C++ looks something like:

void native_algorithm(boost::geometry::model::point const &x) {...}

void python_algorithm(boost::python::object const &x)
{
native_algorithm(static_cast<Point const&>(x));
}

and I have this working for Point, LineString and LinearRing.

However, Polygon has brought me to my knees and challenges my whole
strategy of thinly wrapping the Shapely objects with proxy class references.
I cannot figure out how to extract (I mean boost::python::extract) a
reference to the Shapely geometry in the attributes of a Shapely Polygon.
E.g. where 'p' is a const reference to my C++ proxy Polygon class:

extract<boost::python::object const &>(p.attr("exterior"));

I get the error:

TypeError: No registered converter was able to extract a C++ reference
to type boost::python::api::object from this Python object of type
LinearRing

And this is where I am stuck. I just want a reference to this attribute so
that I can static_cast it to a const reference to my C++ proxy LinearRing
class. Maybe my whole approach is flawed, but if there is a way to solve
this specific glitch in my program then I think I'll be OK. I guess I'm
surprised that it does not work since the same idea of polymorphism around
the python base object class seems to work with function argument
references.
Anyway if however you recommend a completely different approach, I would be
interested in hearing that too.

Thanks, cheers.

Jeremy
Stefan Seefeld
2015-08-18 21:41:15 UTC
Permalink
Hi Jeremy,

I think you have a fundamental misunderstanding of the Boost.Python API,
so I suggest you step back a little to first get a better sense of how
Post by Jeremy Murphy
struct Point : public boost::python::object {}
struct LinearRing : public boost::python::object {}
There is really no point in deriving your own types from
boost::python::object. Instead, you should take your own (existing !)
types and embedd them into Python objects using a mechanism described in
detail in the Boost.Python tutorial:
http://boostorg.github.io/python/doc/html/tutorial/tutorial/exposing.html
Post by Jeremy Murphy
which I can then adapt by specializing the required traits class
void native_algorithm(boost::geometry::model::point const &x) {...}
void python_algorithm(boost::python::object const &x)
{
native_algorithm(static_cast<Point const&>(x));
}
(I'm not entirely understand what you are trying here. Notably, what's
the relationship between the type 'Point' (which you have defined above)
and boost::geometry::model::python ?)

I suggest you start by carefully reading the tutorial referenced above,
to see how C++ objects can be embedded into (and extracted from) Python
objects.
That may not yet answer all your questions, but I'm convinced that once
you understand the techniques described there, you will ask
fundamentally different questions, which I'll gladly try to answer. :-)

Regards,
Stefan
--
...ich hab' noch einen Koffer in Berlin...
Loading...