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

Alf P. Steinbach /Usenet alf.p.steinbach+usenet at gmail.com
Fri Jul 9 11:52:14 EDT 2010


[Cross-posted comp.lang.python and comp.lang.c++]

I lack experience with shared libraries in *nix and so I need to ask...

This is about "cppy", some support for writing Python extensions in C++ that I 
just started on (some days ago almost known as "pynis" (not funny after all)).

For an extension module it seems that Python requires each routine to be defined 
as 'extern "C"'. And although e.g. MSVC is happy to mix 'extern "C"' and C++ 
linkage, using a routine declared as 'static' in a class as a C callback, 
formally they're two different kinds, and I seem to recall that /some/ C++ 
compiler balks at that kind of mixing unless specially instructed to allow it. 
Perhaps it was the Sun compiler?

Anyway, to be formally correct I cannot generate the required C routines via 
templating, and I ended up using macros that the user must explicitly invoke, 
like, here the Py doc's first extension module example recoded using cppy,


------------------------------------------------------------------
<code file="spam.cpp">
#include <progrock/cppx/devsupport/better_experience.h>
#include <progrock/cppy/Module.h>
using namespace progrock;

class Spam: public cppy::Module
{
public:
     Spam(): cppy::Module( "spam" )
     {
         setDocString( L"blåbærsyltetøy er blått" );
     }

     PyObject* system( PyObject* args )
     {
         const char *command;
         int sts;

         if( !PyArg_ParseTuple( args, "s", &command ) )
         {
             return NULL;
         }
         sts = ::system( command );
         return Py_BuildValue( "i", sts );
     }
};

CPPY_MODULE_CROUTINE( Spam, system, "Execute a shell command" )

PyMODINIT_FUNC PyInit_spam()
{
     return cppy::init< Spam >();
}
</code>
------------------------------------------------------------------


It works in Windows.

But here CPPY_MODULE_CROUTINE does three things:

   A Defining the 'extern "C"' routine.
     I cannot think of any problem here.

   B Defining installation data for that routine.
     Possible problem: initializing a static with address of routine?

   C -> Adding that install data record into a linked list!
     Possible problem: are dynamic initialization actions guaranteed
     to be performed in *nix shared library?

Problem (C) is outside the realm of the C++ standard, since the C++ standard 
doesn't support shared libraries, and I've never actually used *nix shared 
libraries so I don't /know/...

Is such dynamic initialization guaranteed?

For completeness, the macro definition (the 0 in there is a list next-pointer):


<code>
#define CPPY_MODULE_CROUTINE_DEF( cppClassName, name )                  \
     extern "C"                                                          \
     static PyObject* cppClassName##_##name( PyObject*, PyObject* args ) \
     {                                                                   \
         return ::progrock::cppy::module<cppClassName>().name( args );   \
     }

#define CPPY_MODULE_CROUTINE_INSTALLDATA( cppClassName, name, docString )   \
     static ::progrock::cppy::detail::ModuleRoutineDescriptor                \
     cppClassName##_##name##_descriptor = {                                  \
         0,                                                                  \
         #name,                                                              \
         docString,                                                          \
         &cppClassName##_##name                                              \
         };                                                                  \
                                                                             \
     static bool cppClassName##_##name##_descriptor_installed =              \
         ::progrock::cppy::detail::addToList< cppClassName >(                \
             cppClassName##_##name##_descriptor                              \
             );

#define CPPY_MODULE_CROUTINE( cppClassName, name, docString )               \
     CPPY_MODULE_CROUTINE_DEF( cppClassName, name )                          \
     CPPY_MODULE_CROUTINE_INSTALLDATA( cppClassName, name, docString )
</code>


TIA.,

- Alf

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



More information about the Python-list mailing list