Cpp + Python: static data dynamic initialization in *nix shared lib?

Alf P. Steinbach /Usenet alf.p.steinbach+usenet at gmail.com
Wed Jul 14 06:39:17 EDT 2010


* Hrvoje Niksic, on 14.07.2010 10:17:
> "Alf P. Steinbach /Usenet"<alf.p.steinbach+usenet at gmail.com>  writes:
>
>> Also, things like the 'owned' option is just asking for trouble.
>
> Isn't owned=true (or equivalent) a necessity when initializing from a
> PyObject* returned by a function declared to return a "new reference"?

No, not quite.

Consider this signature (PyCXX):

    String( PyObject* pyob, bool owned = false )

versus this (cppy):

    PyString( PyPtr object )

With the first signature, every time you construct a String you have to remember 
to (explicitly or implicitly) set the bool flag correctly depending on where the 
actual argument value comes from.

With the second signature the /type/ of the actual argument decides, 
automatically, so there's much less room for messing things up.

With the second signature, if the actual argument is a raw PyObject* pointer 
then it's not owned, and the PyPtr formal argument doesn't increment the 
reference count but just takes ownership. If the actual argument, on the other 
hand, is a PyPtr, then the object is owned by the collection of PyPtr instances 
that refer to the object, and the new formal argument PyPtr instance then 
increments the reference count. In passing, if it should happen that the Python 
community uses the word 'owned' in the opposite sense of what's conventional in 
C++, then I guess & hope you'll figure out what I mean from this description.

PyPtr currently looks like this (complete code):


<code file="PyPtr.h">
// progrock.cppy  --  "C++ plus Python"
// A simple C++ framework for writing Python 3.x extensions.
//
// Copyright (c) Alf P. Steinbach, 2010.

#ifndef CPPY_PYPTR_H
#define CPPY_PYPTR_H
#include <progrock/cppx/devsupport/better_experience.h>


//----------------------------------------- Dependencies:

#include <Python.h>
#include <assert.h>
#include <algorithm>



//----------------------------------------- Interface:

namespace progrock{ namespace cppy {
     using namespace cppx;

     enum DoAddRef {};

     class PyPtr
     {
     private:
         PyObject*   p_;

     public:
         typedef cppy::DoAddRef  DoAddRef;

         PyPtr( PyObject* p = 0 ): p_( p ) {}

         PyPtr( PyObject* p, DoAddRef ): p_( p )
         {
             assert( p != 0 );  Py_INCREF( p_ );
         }

         PyPtr( PyPtr const& other ): p_( other.p_ ) { Py_XINCREF( p_ ); }

         ~PyPtr() { Py_XDECREF( p_ ); }

         void swapWith( PyPtr& other )   { std::swap( p_, other.p_ ); }
         PyPtr& operator=( PyPtr other ) { swapWith( other ); return *this; }

         PyObject* get() const           { return p_; }

         PyObject* release()
         {
             PyObject* const result  = p_;
             p_ = 0;
             return result;
         }
     };

     inline PyObject* withAddedRef( PyObject* p )
     {
         Py_INCREF( p );
         return p;
     }

     inline PyObject* pyNoneRef()
     {
         return withAddedRef( Py_None );
     }
} }  // namespace progrock::cppy


#endif
</code>


As you can see at the end there, there is 'withAddedRef' and 'pyNoneRef', and 
for that matter the 'DoAddRef' and the 'release()' method, for the cases where 
PyPtr default handling doesn't quite cut it... :-)


> How does your API deal with the distinction between new and borrowed
> references?

See above.

There are some cases where it must be dealt with, but the main idea is to encode 
that into /types/, instead of as context-dependent figure-it-out.

That's also the main idea of C++ as compared to C, to encode much more into 
types, which helps both for compile time error detection and for automating 
things (like above), which is Very Nice, but which also can make for enormous 
waste of time trying to make the darned language do what you want it to do! :-)


Cheers & hth.,

- Alf


Disclaimer: it's late in the day/night for me, so the above explanation may have 
big logic holes, mispelings and so on, but I hope it gives the idea.

-- 
blog at <url: http://alfps.wordpress.com>



More information about the Python-list mailing list