[Pyrex] Platform dependent external declarations?

Eric Huss e-huss at netmeridian.com
Thu Mar 1 22:05:38 UTC 2007


On Thu, 1 Mar 2007, Greg Ewing wrote:

> Eric Huss wrote:
>
> > cdef extern from "sys/types.h":
> >     ctypedef unsigned int time_t
> >
> > def foo(time_t x):
> >     print x
> >
> > will generate different code from:
> >
> > cdef extern from "sys/types.h":
> >     ctypedef int time_t
> >
> > def foo(time_t x):
> >     print x
>
> Okay, I see what the problem is now. Different conversion
> functions are used to convert to and from Python objects
> depending on the signedness.
>
> But is this really a problem in practice? Seems to me that
> if the same thing is declared unsigned on some platforms
> but not others, then either the values never extend into
> the range where the sign matters, or it really is unsigned,
> even if some platforms don't bother declaring it as such.
> In either case, declaring it as unsigned to Pyrex should
> work.
>
> Does anyone have any use cases where this would fail?

Well, a more realistic, concrete example would be the difference between
32 and 64 bit platforms, such as:

# 32-bit platform.
cdef extern from "inttypes.h":
    ctypedef int int32_t
    ctypedef unsigned int uint32_t
    ctypedef long long int64_t
    ctypedef int32_t intptr_t
    ctypedef uint32_t uintptr_t

# 64-bit platform (LP64 such as amd64).
cdef extern from "inttypes.h":
    ctypedef int int32_t
    ctypedef long int64_t
    ctypedef unsigned long uint64_t
    ctypedef int64_t intptr_t
    ctypedef uint64_t uintptr_t

Notice that intptr_t cannot be defined as just one type on both platforms
and still be the same. An example of something that uses this is kevent:

cdef extern from "sys/event.h":
    cdef struct kevent:
        uintptr_t ident
        short filter
        unsigned short flags
        unsigned int fflags
        intptr_t data

Using the wrong type for the platform will generate incorrect C code.

Additionally, if you define something like int64_t as "long long" for both
platforms, it will mostly work, but if you need to convert from/to Python
values, on the 64-bit platform it will use the less efficient
PyLong_FromLongLong instead of PyInt_FromLong.

I also use Sam's conditional compilation feature to handle interface
versioning.  One example is that we have a lot of code that interfaces
with low-level system interfaces such as kevent, and we need our code to
compile on various platforms where some constants and data structures are
defined differently.  Another example is my mysql library
(http://ehuss.org/mysql/).  I have various %if conditionals to allow
people to compile against various versions of mysql, particularly as
modifications (such as new functions) are made to the mysql API.

-Eric



More information about the Pyrex mailing list