Packed structures?

203 views
Skip to first unread message

John Mudd

unread,
Apr 9, 2013, 6:14:40 PM4/9/13
to pytho...@googlegroups.com
I have some C functions that required packed structures (alignment=1). I tried the following and it didn't help. Any suggestions?

ffi.cdef('''
#pragma pack(1)

    typedef struct BLOB_REC {
       char a;
       int i;
    } BLOB_REC;
''')

print 'ffi.sizeof("BLOB_REC")=%s' % `ffi.sizeof("BLOB_REC")`
print 'ffi.alignof("BLOB_REC")=%s' % `ffi.alignof("BLOB_REC")`

Output:

ffi.sizeof("BLOB_REC")=8
ffi.alignof("BLOB_REC")=4

John

Armin Rigo

unread,
Apr 10, 2013, 5:47:25 AM4/10/13
to pytho...@googlegroups.com
Hi John,

On Wed, Apr 10, 2013 at 12:14 AM, John Mudd <john...@gmail.com> wrote:
> I have some C functions that required packed structures (alignment=1). I
> tried the following and it didn't help. Any suggestions?

As this is relying on your compiler's details, the standard answer is
to use a struct that is declared with "...;", after which you need to
call ffi.verify() and not ffi.dlopen():

typedef struct BLOB_REC {
char a;
int i;
...;
} BLOB_REC;


I hope you're not afraid to use ffi.verify(), like some persons seem
to be. If you are, then you could make a bogus struct declaration
like "char a; char i[4];" and convert manually between the array i and
its integer value.


A bientôt,

Armin

Simon Sapin

unread,
Apr 10, 2013, 8:08:30 AM4/10/13
to pytho...@googlegroups.com
Le 10/04/2013 11:47, Armin Rigo a �crit :
> I hope you're not afraid to use ffi.verify(), like some persons seem
> to be.

I would like to say that avoiding .verify() is not only based on
irrational fear. There are real reasons to prefer .dlopen(), especially
when you want other people to use your project.


The upside of using .verify() instead of .dlopen() exist because it uses
a C compiler. The downside is that it requires a C compiler.

The documentation says:

> If you use CFFI and verify() in a project that you plan to
> distribute, other users will install it on machines that may not have
> a C compiler. Here is how to write a setup.py script using distutils
> in such a way that the extension modules are listed too. This lets
> normal setup.py commands compile and package the C extension modules
> too.

But this is misleading. Although such a setup means that a C compiler is
not used at runtime, it is still required when installing from source
which often happens on the same machine.


When I tell my users to run "pip install weasyprint", they don�t want to
know about cairocffi or CFFI. Some don�t even what to know about Python.
If they happen to be on Windows, there is a very low probability that
they have a functional C compiler.

Even when the system does have a compiler, it�s not always obvious how
to configure it (include_dirs, library_dirs, �) in a way that works of
different systems.

On the other hand, I don�t want to maintain a bunch of pre-compiled
distributions for a bunch of platforms (that I may not have access to)
and a bunch of Python versions.

So far, pure-Python source distributions on PyPI and using .dlopen() is
the only viable scenario that I found for users on all kinds of platforms.

(Someone else is maintaining pre-compiled builds for CFFI:
http://www.lfd.uci.edu/~gohlke/pythonlibs/#cffi )


But if there are work-arounds for the these issues, I�d love to hear
about it!


Cheers,
--
Simon Sapin

Armin Rigo

unread,
Apr 10, 2013, 10:19:43 AM4/10/13
to pytho...@googlegroups.com
Hi Simon,

On Wed, Apr 10, 2013 at 2:08 PM, Simon Sapin <simon...@exyr.org> wrote:
>> I hope you're not afraid to use ffi.verify(), like some persons seem
>> to be.
>
> I would like to say that avoiding .verify() is not only based on irrational
> fear. There are real reasons to prefer .dlopen(), especially when you want
> other people to use your project.

Yes, you're right. All these issues exist and are annoying. They are
all exactly the same as when distributing a CPython C extension
module, though; so the issues are exactly as annoying as the ones you
have to distribute your code on CPython if it makes use of a custom C
extension module (and yes, I always forget how annoying it can be for
Windows distributions in particular).

If I made a bogus remark I apologize. It was based on the available
alternatives to CFFI: they are C extensions modules, Cython, SWIG,
etc., all of which (apart from ctypes and cffi-with-dlopen) have the
same requirement.


A bientôt,

Armin.

Simon Sapin

unread,
Apr 10, 2013, 10:43:58 AM4/10/13
to pytho...@googlegroups.com
Le 10/04/2013 16:19, Armin Rigo a �crit :
> Hi Simon,
>
> On Wed, Apr 10, 2013 at 2:08 PM, Simon Sapin<simon...@exyr.org> wrote:
>>> I hope you're not afraid to use ffi.verify(), like some persons seem
>>> to be.
>>
>> I would like to say that avoiding .verify() is not only based on irrational
>> fear. There are real reasons to prefer .dlopen(), especially when you want
>> other people to use your project.
> Yes, you're right. All these issues exist and are annoying. They are
> all exactly the same as when distributing a CPython C extension
> module, though; so the issues are exactly as annoying as the ones you
> have to distribute your code on CPython if it makes use of a custom C
> extension module (and yes, I always forget how annoying it can be for
> Windows distributions in particular).

Yes indeed. C extension modules, Cython and SWIG have the same issues as
CFFI-with-verify.

CFFI-with-dlopen has the portability of ctypes without the pain, which
is great! This is worth the downsides for my usage.

(For example, cairocffi generates the declarations given to ffi.cdef()
by parsing the actual cairo*.h files, so verifying is less important.
The generated declarations are shipped together with the source code.)

--
Simon Sapin
Reply all
Reply to author
Forward
0 new messages