[PyQt] Platforms directive or tags, or both?

Larry Shaffer larrys at dakotacarto.com
Thu Oct 18 21:45:30 BST 2012


Hi Jens,

On Thu, Oct 18, 2012 at 10:49 AM, Jens Thoms Toerring <jt at toerring.de> wrote:
> Hi,
>
> On Thu, Oct 18, 2012 at 09:42:30AM -0600, Larry Shaffer wrote:
>> I'm working on a fix for Mac (for QGIS project) where size_t needs a
>> different typedef in a sip file than other platforms.
>>
>> See: http://hub.qgis.org/issues/6505
>>
>> The build system is CMake that passes -t WS_MACX from the found PyQt4
>> config on the command line. So, I wrote a simple:
>>
>> %If (WS_MACX)
>> typedef unsigned long size_t;
>> %End
>> %If (!WS_MACX)
>> typedef unsigned int size_t;
>> %End
>
> Since what size_t is is rather platform dependend I'd suggest
> to use a different way that determines its type in the process
> of making the SIP project. For this I have the following func-
> tion defined in my 'configure.py'  script
>
> -------------8<--------------------------------------
>
> def create_size_t_sip( configuration ) :
>     """
>     Creates and runs a program that writes out a file named 'size_t.sip',
>     containing the correct typedefs for size_t and ssize_t for the system
>     we're going to built the wrapper library on.
>     """
>
>     name = 'size_t_check.cpp';
>
>     if os.path.exists( './size_t.sip' ) :
>         return
>
>     open( name, 'w' ).write(
> '''#include <cstdlib>
> #include <fstream>
> #include <typeinfo>
> using namespace std;
> int main( ) {
>     ofstream f;
>     f.open( "size_t.sip", ios::out );
>     if ( ! f.is_open( ) )
>         return EXIT_FAILURE;
>
>     if ( typeid( size_t ) == typeid( unsigned int ) )
>         f << "typedef unsigned int size_t;\\n"
>           << "typedef int ssize_t;\\n";
>     else if ( typeid( size_t ) == typeid( unsigned long int ) )
>         f << "typedef unsigned long size_t;\\n"
>           << "typedef long ssize_t;\\n";
>     else
>         f << "typedef unsigned long long size_t;\\n"
>           << "typedef long long ssize_t;\\n";
>
>     f.close( );
>     return 0;
> }
> ''' )
>
>     makefile = pyqtconfig.sipconfig.ProgramMakefile( configuration,
>                                                      console = True )
>
>     # This flag doesn't seem to be set in the Windows build of python, but
>     # it's necessary for the (Windows) library to allow use of exceptions
>
>     if sys.platform == 'win32' :
>         makefile.extra_cxxflags.append ( '/EHsc' )
>
>     exe, build = makefile.build_command( name )
>
>     # On Unix we may need './' before the name of the executable while
>     # on Windows with Visual Studio 2008 the program doesn't get run when
>     # the '/MD' option (which is for DLLs) is used (we can't be sure if
>     # the option is given as '-MD' or as '/MD' so check for both).
>
>     if sys.platform != 'win32' :
>         exe = './' + exe
>     else :
>         build = build.replace( '-MD', '' )
>         build = build.replace( '/MD', '' )
>
>     if os.system( build ) != 0 :
>         print "Failed to create program for creating size_t.sip"
>         exit( )
>
>     os.remove( name )
>
>     if os.system( exe ) != 0 :
>         print 'Failed to run program for creating size_t.sip'
>         os.remove( exe )
>         exit( )
>
>     os.remove( exe )
>
> -------------8<--------------------------------------
>
> This is supposed to write out a small (C++) test program, com-
> pile and then run it, writing out a file named 'size_t.sip'
> with the correct definition of size_t (and also 'ssize_t').
> This 'size_t.sip' file should be made part of the list of SIP
> files you that make up your project. The abouve function would
> be called in 'configure,py' rather early, possibly like this
>
> config = pyqtconfig.Configuration( )
> create_size_t_sip( config )

Interesting approach. Thank you for sharing. Since the QGIS project
has a minimum requirement of Python 2.3 (2.5+ recommended), I think
maybe the Python ctypes package could be leveraged instead of
generating a cpp test program. I will have to ask the other QGIS devs,
with more knowledge in this area, if that approach is better than the
current platform-sniffing, hard-coded way.

On my Mac (Py 2.7.1), I did this:

import ctypes
ctypes.c_size_t == ctypes.c_ulong
# returns True
ctypes.c_size_t == ctypes.c_uint
# returns False

So it looks like a variation on your script will work, since Python is
already used as part of the CMake finds before generating the sip
files for the bindings. CMake (or Python) can then be used to generate
the sip file from the returned typedef string. Thanks again.

> I only have tested this with Linux and Windows (with V2008),
> some tweaks may be necessary for the Mac platform which I
> don't have access to,
>                             Best regards, Jens
> --
>   \   Jens Thoms Toerring  ________      jt at toerring.de
>    \_______________________________      http://toerring.de


More information about the PyQt mailing list