[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