Kenneth Duda | 9 May 23:19
Picon

Re: Making smart pointers a bit smarter

Thanks for the comments.  I agree with all of the limitations you
point out (though they happen to not matter for the smart pointers I'm
using).

> Why not check for nullness on the other end, in the wrapper functions that
> dereference the smart pointers?  I think that that avoids all these
> problems.  

This sounds like it would be better.  How would you imagine checking
for nullness, if testing operator->() for NULL can't be trusted?  I
suppose I could wrap the null check in a try block and treat any
exception as equivalent to NULL.  Would you recommend that?

> Better yet, why not move much of smart pointer support out of C++ and into
> the target language?

Let me see if I understand this suggestion. It means eliminating most
methods of the wrapped C++ smart pointer, leaving only __deref__ and
__notzero__ (that could do the NULL test safely); then, modify the
python wrapper of the smart pointer so instead of saying

   def someMethod(*args): return _MyLibrary.MyClassSmartptr_someMethod( *args )

it would say

   def someMethod(self, *args):
      if self: return self.__deref__().someMethod( *args )
      else: raise NullPointerException()

If this is right, I'd tend to agree it's better than the current smart
pointer approach.  I have no idea how much work this would be to do
within swig, however.  (I figured my original proposal would be a
modest incremental change, whereas this fundamentally changes the way
smart pointers are wrapped).

So it sounds like there are three proposals on the table:

  A) my original proposal --- any smart pointer whose operator->
returns NULL gets coverted to None; anything expecting a smart pointer
accepts None and passes in NULL.

  B) Josh's proposal of moving the NULL check into the wrapped methods.

  C) Josh's second proposal (as interpreted by me) for changing the
C++-level wrapping of a smart pointer classes to not incorporate
wrapped methods of the underlying object at all, but rather null-check
and delegate in the python-level wrapper of the smart pointer class.

I guess I lean towards "B".  Any other thoughts?

     -Ken

On 5/9/05, Josh Cherry <jcherry <at> ncbi.nlm.nih.gov> wrote:
> 
> On Sun, 8 May 2005, Kenneth Duda wrote:
> 
> > "None" is much friendlier than a wrapped NULL smart pointer --- it's
> > easy to test for "None", and if you try to use it as a pointer, you
> > get a sensible Python exception (rather than a SEGV).
> >
> > All of this is fine --- the reason I'm writing is I would like to make
> > this improved smart pointer wrapping the default behavior of SWIG.
> > Before I spend the time to do so, I wanted to guage the interest level
> > from the SWIG maintainers --- is the patch likely to be accepted
> > (assuming I code it competently), or is it something you're not
> > interested in (i.e., is there a good reason to not do this)?
> 
> I understand the motivation for doing this, but I also see some
> downsides, and some ways to protect against segfaults while avoiding the
> downsides.
> 
> Sometimes in C++ one creates a smart pointer that points at NULL and
> subsequently modifies it, using methods of the smart pointer class.  This
> way of doing things would be impossible with None.  Also, there is
> potential for loss of information and for throwing away a useful object.
> This isn't an issue for a smart pointer that contains a pointer as its
> sole data member, which is returned by operator->, but not all smart
> pointers are like that.  Perhaps operator-> returns NULL but the object is
> full of information and has other methods that are still very useful
> (perhaps I can decrement my pointer and it will now point at something;
> perhaps operator-> is a minor part of what the class does, and returns
> NULL more often then not).
> 
> Another problem is that the code you want to generate will call operator->
> on NULL smart pointers.  The code I'm wrapping has smart pointer classes
> whose operator-> checks whether the pointer is null and throws an
> exception if it is.  So I would never wind up with None; I would get an
> exception instead, which I don't think would even be caught (as bad as a
> segfault).
> 
> There's also potential for confusing a non-null pointer to a null smart
> pointer with a null pointer to a smart pointer.  In fact, how would I pass
> a null smart pointer by value?  Pass None?  The default "in" typemap will
> reject this as a null pointer (to smart pointer).
> 
> Why not check for nullness on the other end, in the wrapper functions that
> dereference the smart pointers?  I think that that avoids all these
> problems.  It doesn't allow you to test for nullness by comparing to None,
> but you can always compare foo.__deref__() to None, and smart pointers
> often provide methods for testing for nullity.
> 
> Better yet, why not move much of smart pointer support out of C++ and into
> the target language?  Python methods could simply call
> self.__deref__().Func(), which would automatically protect against null
> pointers.  I've been interested in this for another reason: smart pointer
> support greatly increases the size of wrapper code because lots of methods
> get wrapped multiple times.
> 
> Josh
> 
> --
> Joshua L. Cherry, Ph.D.
> NCBI/NLM/NIH (Contractor)
> jcherry <at> ncbi.nlm.nih.gov
> 
>
_______________________________________________
Swig maillist  -  Swig <at> cs.uchicago.edu
http://mailman.cs.uchicago.edu/mailman/listinfo/swig


Gmane