[C++-sig] from_python converter problem, unable to match C++ signature

Mark Kirk mklists at gmail.com
Mon Nov 13 22:44:24 CET 2006


David,

Thanks for responding;  I really appreciate it.  You cleared up a few things
for me,
and your suggestions got me half-way there.  The converter works now for the
member
function, but still no luck with the constructor.  I'll explain below.

I think there are some good points made here for other boost.python novices
like myself, so
I want to comment on a few things.  Hopefully, folks in the know will
correct anything I misstate.

On 11/10/06, David Abrahams <dave at boost-consulting.com> wrote:
>
> "Mark Kirk" <mklists at gmail.com> writes:
> > This Python extension makes its symbols
> > globally available through a call to sys.setdlopenflags(dl.RTLD_NOW |
> > dl.RTLD_GLOBAL).
>
> That makes everybody's symbols globally available, potentially causing
> clashes which might be silent ODR violations causing all sorts of
> havoc.  That said, if you control all the C++ names in the system, and use
> namespaces carefully, you'll probably be OK.


I should have added that the dlopen flags are reset in the __init__.py after
the extension is imported:

flags = sys.getdlopenflags()
sys.setdlopenflags(dl.RTLD_NOW | dl.RTLD_GLOBAL)
import _foo
# Reset the dlopen flags
sys.setdlopenflags(flags)
del flags

This limits the export to just this extension's symbols unless I'm missing
something.


>
> > struct foo_from_python
> > {
> >     static FOO*& execute(PyObject& p)
> >     {
> >         static FOO* a = FooObject_ptr(&p);
>           ^^^^^^
> hey; what's up with that?
> >         return a;
> >     }
> > };


Heh... yeah, that was pretty bogus, but I was hacking around the compiler
being upset
about initializing a reference from a temporary (even though it would have
been valid after
the function call ended).  I thought I'd get rid of that "static" cheat
later if I could make other
things work.

Late Friday afternoon before I saw your mail, a colleague who had been
looking at this
with me came up with a refinement that worked for converting FOO* in member
functions
(not constructors):

struct foo_from_python
{
    static FOO& execute(PyObject& p)
    {
        return *(FooObject_ptr(&p));
    }
};

BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(FOO);
lvalue_from_pytype<foo_from_python, &FooObject_Type>();

He used the BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID macro to obviate the
need to include the foo_internal.h header.


Don't try to convert to pointers; there are no pointers in
> Boost.Python; only lvalues and rvalues ;-)
>
>   void* extract_foo(PyObject* op)
>   {
>       return FooObject_ptr(op);
>   }
>
>   boost::python::converter::registry::insert(
>             &extractor_foo, boost::python::type_id<FOO>());


Friday night I saw your mail, which *really* cleared up a few things -- not
to try
converting pointers being the most important.  Like a lot of programmers,
I'm afraid
I suffer from an incomplete understanding of lvalue and rvalue.  They have a
history
of ambiguity.  I'd considered a pointer variable to be an lvalue since you
can assign to
it (even though it's holding an address).  Thanks for enlightening me.  I
needed it.

With your suggested solution, I could get rid of foo_Internal.h using the
opaque specialized type_id macro
as above.  I believe that macro simply examines the tp_name field in a
PyTypeObject rather than using
C++ typeid() (which is wrapped by boost::python::type_id()).  Is this an
acceptable way to do this since I
shouldn't really use foo_internal.h?

Unfortunately, I'm still unable to get the constructor to work.  I get
compiler errors from boost.python, but,
after looking through the boost.python source, I'm still stumped.  My
metaprogramming fu is just not
there.  I'm reluctant to post the complete errors here (but I'm happy if
someone is up for it),
so here's an abbreviated version of the chain of five errors:

---------------------
sys_include/boost/python/def_visitor.hpp: In static member function `static
void boost::python::def_visitor_access::visit(const V&, classT&, const
char*, const OptionalArgs&) [with V =
boost::python::def_visitor<boost::python::init<ANI*, mpl_::void_,
mpl_::void_, (many more mpl_::void_ params, most other params are
boost::detail::not_specified)':

sys_include/boost/python/def_visitor.hpp:74:   instantiated from `void
boost::python::def_visitor<DerivedVisitor>::visit(classT&, const char*,
const OptionalArgs&) const [with classT = boost::python::class_<bpani,
boost::python::detail::not_specified, boost::python::detail::not_specified,
boost::python::detail::not_specified>, OptionalArgs =
boost::python::detail::def_helper<const char*, ...

sys_include/boost/python/class.hpp:481:   instantiated from `void
boost::python::class_<T, X1, X2, X3>::def_impl(T*, const char*, LeafVisitor,
const Helper&, const boost::python::def_visitor<Visitor>*) [with T = bpani,
Helper = boost::python::detail::def_helper<const char*,
boost::python::detail::not_specified, boost::python::detail::not_specified,
boost::python::detail::not_specified>, LeafVisitor =
boost::python::init<ANI*, mpl_::void_, mpl_::void_,  ...

sys_include/boost/python/class.hpp:235:   instantiated from
`boost::python::class_<T, X1, X2, X3>& boost::python::class_<T, X1, X2,
X3>::def(const char*, F) [with F = boost::python::init<ANI*, mpl_::void_,
mpl_::void_, mpl_::void_, mpl_::void_, mpl_::void_, mpl_::void_,
mpl_::void_, mpl_::void_, mpl_::void_, mpl_::void_, mpl_::void_,
mpl_::void_, mpl_::void_, mpl_::void_>, W = bpani, X1 =
boost::python::detail::not_specified, X2 =
boost::python::detail::not_specified, X3 =
boost::python::detail::not_specified]'

lib/bpfoo/python/pybpfoo.cc:39:   instantiated from here
sys_include/boost/python/def_visitor.hpp:43: error: no matching function for
call to `boost::python::init<ANI*, mpl_::void_, mpl_::void_, mpl_::void_,
mpl_::void_, mpl_::void_, ...
---------------------

OK, that's still a lot;  sorry about that.  Again, David if you or anyone
has an idea how I can get past this,
I'd really appreciate it.  Feels like it's close.

Well, it's my fault for never making the converter registration
> interface truly public and documenting it.  Sorry about that.


Ha!  Well, yeah, that would have made things easier I suppose, but I'm just
grateful
for having boost.python at all.  It's made wrapping C++ libs extremely
efficient.  Unfortunately,
this particular problem has become a show-stopper for me.  Many of my
colleagues will likely
need to do this eventually, so we must solve it somehow or come up with
another way to
wrap many of our libs (which would be a drag).

thanks,
mark
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20061113/affe8152/attachment.htm>


More information about the Cplusplus-sig mailing list