<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Mon, Nov 26, 2018 at 4:10 PM Larry Hastings <<a href="mailto:larry@hastings.org">larry@hastings.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  
    
  
  <div text="#000000" bgcolor="#FFFFFF">
    <div class="m_-4684155198716332097moz-cite-prefix">On 11/23/18 5:15 AM, Armin Rigo wrote:<br>
    </div>
    <blockquote type="cite">
      <pre class="m_-4684155198716332097moz-quote-pre">Also FWIW, my own 2 cents on the topic of changing the C API: let's
entirely drop ``PyObject *`` and instead use more opaque
handles---like a ``PyHandle`` that is defined as a pointer-sized C
type but is not actually directly a pointer.  The main difference this
would make is that the user of the API cannot dereference anything
from the opaque handle, nor directly compare handles with each other
to learn about object identity.  They would work exactly like Windows
handles or POSIX file descriptors.</pre>
    </blockquote>
    <br>
    <p>Why would this be better than simply returning the pointer? 
      Sure, it prevents ever dereferencing the pointer and messing with
      the object, it is true.  So naughty people would be prevented from
      messing with the object directly instead of using the API as they
      should.  But my understanding is that the implementation would be
      slightly slower--there'd be all that looking up objects based on
      handles, and managing the handle namespace too.  I'm not convinced
      the nice-to-have of "you can't dereference the pointer anymore" is
      worth this runtime overhead.</p>
    <p>Or maybe you have something pretty cheap in mind, e.g. "handle =
      pointer ^ 49"?  Or even "handle = pointer ^ (random odd number
      picked at startup)" to punish the extra-naughty?</p></div></blockquote><div>Heck, it'd be find if someones implementation (such as a simple shim for CPython's existing API) wants to internally keep a PyObject structure and have PyHandle's implementation just be a typecast from PyObject* to PyHandle.  The real point is that a handle is opaque and cannot be depended on by any API _user_ as being a pointer.  What it means behind the scenes of a given VM is left entirely up to the VM.</div><div><br></div><div>When an API returns a handle, that is an implicit internal INCREF if a VM is reference counting.  When code calls an API that consumes a handle by taking ownership of it for itself (Py_DECREF could be considered one of these if you have a Py_DECREF equivalent API) that means "I can no longer using this handle".</div><div><br></div><div>Comparisons get documented as being invalid, pointing to the API to call for an identity check, but it is up to each implementation to decide if it wants to force the handles to be unique. Anyone depending on that behavior is being bad and should not be supported.</div><div><br></div><div>-gps</div><div><br></div><div>PS ... use C++ and you could actually make handle identity comparisons do the right thing...</div></div></div>