Re: Problem with alignment under Linux

Axel Seibert <[email protected]> Sun, 13 May 2012 10:27:39 +0200
Newsgroups gmane.comp.python.ctypes
Message-ID <[email protected]>
Dear list!

[I sent this email out a month ago, but have not received any feedback yet. Let me repost my email in the hope that somebody can help me out with that. The current situation makes it impossible for my project to continue under Linux.]
 
It’s been two months since we had our discussion. I have tried to follow your suggestion:
-        check each member of a union for a type which requires the 8 byte alignment and mark that union appropriately if such a type is found (ie double or long long);

-        check each member of a struct for a type which requires the 8 byte alignment, and if such a member is encountered insert appropriate padding before the member

and then you suggested a code snippet.
 
The executive summary is: This approach (at least in the current implementation) seems not to work.
 
I believe for Structures, it could work.
However, for Unions I found the following issues:
1.     in your example below, you suggest a function align_union(union_class), which could be called in _init_. This could be used when my code instantiates such unions; but what about unions that are created by the server side that I’m only trying to read?

2.     Therefore, I changed the sample code; as I know which unions need to be aligned differently, I guess I don’t need this function, and could set class._alignment immediately, e.g.:

class BMCUnion(Union):
    _alignment = 8
 
Unfortunately, this also seems to not work, and I guess, the answer lies here:
 
class N13ARValueStruct3DOLLAR_1E(BMCUnion):
    pass
>>> a=N13ARValueStruct3DOLLAR_1E()
>>> a._alignment
8
>>> alignment(a)
4
 
What am I missing? Are there other variations on this theme which could lead to a solution?
 
Thanx for your input!
Axel
 
Am 14.02.2012 um 09:34 schrieb Andrew MacIntyre:

> I think the comment in the documentation has to be a red herring, as it would make that compiler noncompliant with the Linux i386 ABI by default which would probably cause all sorts of problems compiling other software.
>  
> It seems to me that you will need to do several things:
> -          check each member of a union for a type which requires the 8 byte alignment and mark that union appropriately if such a type is found (ie double or long long);
> -          check each member of a struct for a type which requires the 8 byte alignment, and if such a member is encountered insert appropriate padding before the member.
>  
> The approach that occurs to me is to use an attribute which can be tested for using hasattr() (or AttributeError if you prefer exceptions rather than look before leap).
>  
> Perhaps something along the lines of (untested! and not necessarily all encompassing):
>  
>                 ...
>                 from ctypes import *
>  
>                 ...
>  
>                 # this foreign DLL is built with –malign_double
> c_double._alignment = 8
>                 c_long_long._alignment = 8
>  
>                 ...
>  
>                 # check a Union for members requiring non-standard alignment
>                 def align_union(union_class):
>                                 for n, t in union_class._fields_:
>                                                 if hasattr(t, ‘_alignment’):
>                                                                 union_class._alignment = t._alignment
>                                                                 break
>  
>                 # patch the ‘fields’ sequence of a ctypes Structure by inserting
>                 # dummy fields to achieve required alignment
>                 def pad_struct(fields):
>                                 result = []
>                                 size = 0
>                                 for n, t in fields:
>                                                 if hasattr(t, ‘_alignment’):
>                                                                 padding = size % t._alignment
>                                                                 if padding:
>                                                                                 padding = t._alignment – padding
>                                                                                 result.append((‘’, c_char * padding))
>                                                                                 size += padding
>                                                 size += sizeof(t)
>                                                 result.append((n, t))
>                                 return result
>  
>                 ...
>  
>                 class U(Union):
>  
>                                 _fields_ = ((‘a’, c_long),
>                                                                 (‘b’, c_double))
>  
>                                 def __init__(self):
>                                                 align_union(self)
>                                                 Union.__init__(self)
>  
>                 class S(Structure):
>                                 _fields_ = pad_struct(((‘c’, c_long),
>                                                                                 (‘d’, U)))
>  
>                 ...
>  
> -------------------------> "These thoughts are mine alone!" <---------
> Andrew MacIntyre           Operations Branch
> tel:   +61 2 6219 5356     Communications Infrastructure Division
> fax:   +61 2 6253 3277     Australian Communications & Media Authority
> email: [email protected]            http://www.acma.gov.au/
>  
> From: Axel Seibert [mailto:[email protected]] 
> Sent: Tuesday, 14 February 2012 6:34 AM
> To: [email protected]
> Subject: Re: [ctypes-users] Problem with alignment under Linux [SEC=UNCLASSIFIED]
>  
> Hi, Andrew!
>  
> According to http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html, "aligned" is the attribute to look for.  There is another possibility that occurs to me: the use of the gcc option "-malign-double" forcing doubles to be 8 byte aligned when building the library.
>  
> This is the hint that brought me in the right direction; looking at one of the supplied examples shows that the Makefile under Linux calls the compiler with the following arguments:
>  
> -malign-double
>  
> And the documentation says:
>         Configure the compiler as follows: Structure member alignment: 8 bytes (default)
>  
> In other words, the software supplier requires this for whatever reasons. What can we now deduct from this for my problem?
>  
> Thanx again for your help,
> Axel
>  
>  
> NOTICE: This email message is for the sole use of the intended recipient(s) 
> and may contain confidential and privileged information. Any unauthorized 
> review, use, disclosure or distribution is prohibited. If you are not the 
> intended recipient, please contact the sender by reply email and destroy all 
> copies of the original message.
> 
> ------------------------------------------------------------------------------
> Keep Your Developer Skills Current with LearnDevNow!
> The most comprehensive online learning library for Microsoft developers
> is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
> Metro Style Apps, more. Free future releases when you subscribe now!
> http://p.sf.net/sfu/learndevnow-d2d_______________________________________________
> ctypes-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/ctypes-users

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/

_______________________________________________
ctypes-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ctypes-users