David,<br><br>Thanks for responding; I really appreciate it. You cleared up a few things for me,<br>and your suggestions got me half-way there. The converter works now for the member<br>function, but still no luck with the constructor. I'll explain below.
<br><br>I think there are some good points made here for other boost.python novices like myself, so<br>I want to comment on a few things. Hopefully, folks in the know will correct anything I misstate.<br><br>On 11/10/06,
<b class="gmail_sendername">David Abrahams</b> <<a href="mailto:dave@boost-consulting.com">dave@boost-consulting.com</a>> wrote:<div><span class="gmail_quote"></span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
"Mark Kirk" <<a href="mailto:mklists@gmail.com">mklists@gmail.com</a>> writes:<br>> This Python extension makes its symbols<br>> globally available through a call to sys.setdlopenflags(dl.RTLD_NOW |<br>
> dl.RTLD_GLOBAL).<br><br>That makes everybody's symbols globally available, potentially causing<br>clashes which might be silent ODR violations causing all sorts of<br>havoc. That said, if you control all the C++ names in the system, and use
<br>namespaces carefully, you'll probably be OK.</blockquote><div><br>I should have added that the dlopen flags are reset in the __init__.py after the extension is imported:<br><br>flags = sys.getdlopenflags()<br>sys.setdlopenflags
(dl.RTLD_NOW | dl.RTLD_GLOBAL)<br>import _foo<br># Reset the dlopen flags<br>sys.setdlopenflags(flags)<br>del flags<br><br>This limits the export to just this extension's symbols unless I'm missing something.<br> <br></div>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br>> struct foo_from_python<br>> {<br>> static FOO*& execute(PyObject& p)
<br>> {<br>> static FOO* a = FooObject_ptr(&p);<br> ^^^^^^<br>hey; what's up with that?<br>> return a;<br>> }<br>> };</blockquote><div><br>Heh... yeah, that was pretty bogus, but I was hacking around the compiler being upset
<br>about initializing a reference from a temporary (even though it would have been valid after<br>the function call ended). I thought I'd get rid of that "static" cheat later if I could make other<br>things work.
<br><br>Late Friday afternoon before I saw your mail, a colleague who had been looking at this<br>with me came up with a refinement that worked for converting FOO* in member functions<br>(not constructors):<br><br>struct foo_from_python
<br>{<br> static FOO& execute(PyObject& p)<br> {<br> return *(FooObject_ptr(&p));<br> }<br>};<br><br>BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(FOO);<br>lvalue_from_pytype<foo_from_python, &FooObject_Type>();
</div><br>He used the BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID macro to obviate the<br>need to include the foo_internal.h header.<br><br><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Don't try to convert to pointers; there are no pointers in<br>Boost.Python; only lvalues and rvalues ;-)<br><br> void* extract_foo(PyObject* op)<br> {<br> return FooObject_ptr(op);<br> }<br><br> boost::python::converter::registry::insert(
<br> &extractor_foo, boost::python::type_id<FOO>());</blockquote><div><br>Friday night I saw your mail, which *really* cleared up a few things -- not to try <br>converting pointers being the most important. Like a lot of programmers, I'm afraid
<br>I suffer from an incomplete understanding of lvalue and rvalue. They have a history<br>of ambiguity. I'd considered a pointer variable to be an lvalue since you can assign to<br>it (even though it's holding an address). Thanks for enlightening me. I needed it.
<br><br>With your suggested solution, I could get rid of foo_Internal.h using the opaque specialized type_id macro<br>as above. I believe that macro simply examines the tp_name field in a PyTypeObject rather than using<br>
C++ typeid() (which is wrapped by boost::python::type_id()). Is this an acceptable way to do this since I <br>shouldn't really use foo_internal.h? <br><br>Unfortunately, I'm still unable to get the constructor to work. I get compiler errors from
boost.python, but,<br>after looking through the boost.python source, I'm still stumped. My metaprogramming fu is just not<br>there. I'm reluctant to post the complete errors here (but I'm happy if someone is up for it),
<br>so here's an abbreviated version of the chain of five errors:<br><br>---------------------<br>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)':
<br><br>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*, ...
<br><br>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_, ...
<br><br>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]'
<br><br>lib/bpfoo/python/pybpfoo.cc:39: instantiated from here<br>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_, ...
<br>---------------------<br><br>OK, that's still a lot; sorry about that. Again, David if you or anyone has an idea how I can get past this,<br>I'd really appreciate it. Feels like it's close. <br> <br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Well, it's my fault for never making the converter registration<br>interface truly public and documenting it. Sorry about that.</blockquote><div><br>Ha! Well, yeah, that would have made things easier I suppose, but I'm just grateful
<br>for having boost.python at all. It's made wrapping C++ libs extremely efficient. Unfortunately,<br>this particular problem has become a show-stopper for me. Many of my colleagues will likely<br>need to do this eventually, so we must solve it somehow or come up with another way to
<br>wrap many of our libs (which would be a drag).<br><br>thanks,<br>mark<br><br></div><br></div>