<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=US-ASCII">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2653.12">
<TITLE>AW: AW: [C++-sig] Wrapping opaque pointers returned from API function s</TITLE>
</HEAD>
<BODY>
<BR>
<BR>
<P><FONT SIZE=2>> -----Ursprungliche Nachricht-----</FONT>
<BR><FONT SIZE=2>> Von: David Abrahams [<A HREF="mailto:dave@boost-consulting.com">mailto:dave@boost-consulting.com</A>]</FONT>
<BR><FONT SIZE=2>> Gesendet: Montag, 13. Januar 2003 13:47</FONT>
<BR><FONT SIZE=2>> An: c++-sig@python.org</FONT>
<BR><FONT SIZE=2>> Betreff: Re: AW: [C++-sig] Wrapping opaque pointers returned from API</FONT>
<BR><FONT SIZE=2>> function s</FONT>
<BR><FONT SIZE=2>> </FONT>
<BR><FONT SIZE=2>> </FONT>
<BR><FONT SIZE=2>> Gottfried.Ganssauge@HAUFE.DE writes:</FONT>
<BR><FONT SIZE=2>> </FONT>
<BR><FONT SIZE=2>> >> I didn't say I tested the code ;-)</FONT>
<BR><FONT SIZE=2>> ></FONT>
<BR><FONT SIZE=2>> > Of course.</FONT>
<BR><FONT SIZE=2>> > Anyway, your upcast is probably invalid anyway, because </FONT>
<BR><FONT SIZE=2>> PyObject ist not a</FONT>
<BR><FONT SIZE=2>> > base class of instance.</FONT>
<BR><FONT SIZE=2>> </FONT>
<BR><FONT SIZE=2>> No, it is not invalid. My upcast template is specially designed to</FONT>
<BR><FONT SIZE=2>> deal with this. Please try doing as I suggested.</FONT>
<BR><FONT SIZE=2>Here you are:</FONT>
<BR><FONT SIZE=2>c:\daten\devel\boost\boost\python\cast.hpp(31) : error C2039: 'type' : Ist kein Element von 'base_type_traits<struct convert_opaque_pointer<struct workspace_ *>::instance>'</FONT></P>
<P><FONT SIZE=2>c:\daten\devel\boost\boost\python\cast.hpp(52) : Siehe Verweis auf Instantiierung der kompilierten Funktionsvorlage 'struct _object *__cdecl boost::python::detail::upcast(struct convert_opaque_pointer<struct workspace_ *>::instance *,int *,int *,struct _object *)'</FONT></P>
<P><FONT SIZE=2>I had seen that message before and concluded from it, that convert_opaque_pointer<struct workspace_ *>::instance * can't be converted to PyObject * using upcast<>.</FONT></P>
<P><FONT SIZE=2>> </FONT>
<BR><FONT SIZE=2>> >> No, that's non-POD. It has a base class. </FONT>
<BR><FONT SIZE=2>> ></FONT>
<BR><FONT SIZE=2>> > I think I have a solution that is hopefully more conforming </FONT>
<BR><FONT SIZE=2>> but doesn't rely</FONT>
<BR><FONT SIZE=2>> > on the Python implementation details (and it even resembles </FONT>
<BR><FONT SIZE=2>> a bit to real</FONT>
<BR><FONT SIZE=2>> > inheritance)</FONT>
<BR><FONT SIZE=2>> > struct instance {</FONT>
<BR><FONT SIZE=2>> > PyObject base_;</FONT>
<BR><FONT SIZE=2>> > Pointer x;</FONT>
<BR><FONT SIZE=2>> > };</FONT>
<BR><FONT SIZE=2>> </FONT>
<BR><FONT SIZE=2>> The contents of PyObject are still Python implementation details.</FONT>
<BR><FONT SIZE=2>True, but I don't use it. PyObject_HEAD may be the implementation of PyObject but there is no direct relationship between the two except Guido. (no criticism; just a fact)</FONT></P>
<P><FONT SIZE=2>> This one is no better than my proposal, and may in fact take extra</FONT>
<BR><FONT SIZE=2>> storage for alignment.</FONT>
<BR><FONT SIZE=2>At least it doesn't need a cast :-)</FONT>
<BR><FONT SIZE=2>Why should there be extra alignment storage used after PyObject but not after PyObject_HEAD?</FONT>
</P>
<P><FONT SIZE=2>> </FONT>
<BR><FONT SIZE=2>> > static PyObject* convert(Pointer x)</FONT>
<BR><FONT SIZE=2>> > {</FONT>
<BR><FONT SIZE=2>> > instance *o = PyObject_New (instance, &type_object);</FONT>
<BR><FONT SIZE=2>> > o->x = x;</FONT>
<BR><FONT SIZE=2>> > return &o->base_;</FONT>
<BR><FONT SIZE=2>> > }</FONT>
<BR><FONT SIZE=2>> > I can't lookup the paragraph in the standard, but I found </FONT>
<BR><FONT SIZE=2>> something in the</FONT>
<BR><FONT SIZE=2>> > draft of "C++ in a nutshell".</FONT>
<BR><FONT SIZE=2>> > In Chapter 7 it says:</FONT>
<BR><FONT SIZE=2>> > """</FONT>
<BR><FONT SIZE=2>> > A POD class can contain padding between data members, but </FONT>
<BR><FONT SIZE=2>> no padding appears</FONT>
<BR><FONT SIZE=2>> > before the first member. Therefore, a pointer to the POD </FONT>
<BR><FONT SIZE=2>> object can be</FONT>
<BR><FONT SIZE=2>> > converted (with reinterpret_cast<>) to a pointer to the </FONT>
<BR><FONT SIZE=2>> first element.</FONT>
<BR><FONT SIZE=2>> > """</FONT>
<BR><FONT SIZE=2>> </FONT>
<BR><FONT SIZE=2>> They're wrong about reinterpret_cast<>, as far as the standard goes.</FONT>
<BR><FONT SIZE=2>> That performs an implementation-defined mapping. The only thing you</FONT>
<BR><FONT SIZE=2>> can do portably with it is convert a pointer to a different type and</FONT>
<BR><FONT SIZE=2>> back again, without using it in between. Please, just try it the way</FONT>
<BR><FONT SIZE=2>> I suggested!</FONT>
<BR><FONT SIZE=2>My solution only uses the fact, that there is no extra padding before the base_ member so that a pointer to base_ may be returned from the convert method that can be converted back to a pointer to our instance struct.</FONT></P>
<P><FONT SIZE=2>Cheers,</FONT>
</P>
<P><FONT SIZE=2>Gottfried</FONT>
</P>
</BODY>
</HTML>