Geoff Clements added the comment: Thank you eryksun for the explanation. It's much appreciated. I'll take a look at CFFI. On 1 Nov 2014 22:38, "eryksun" <rep...@bugs.python.org> wrote:
> > eryksun added the comment: > > ctypes doesn't always handle bitfields correctly. In particular it doesn't > adapt the storage unit size when packed. A bitfield based on c_uint is > always stored in 4 bytes, even if _pack_ is set to 1. This is MSVC rules, > so all is well on Windows. > > For example, from ifo_types.h: > > typedef struct { > unsigned int zero_1 : 1; > unsigned int multi_or_random_pgc_title : 1; /* 0: one sequential pgc > title */ > unsigned int jlc_exists_in_cell_cmd : 1; > unsigned int jlc_exists_in_prepost_cmd : 1; > unsigned int jlc_exists_in_button_cmd : 1; > unsigned int jlc_exists_in_tt_dom : 1; > unsigned int chapter_search_or_play : 1; /* UOP 1 */ > unsigned int title_or_time_play : 1; /* UOP 0 */ > } ATTRIBUTE_PACKED playback_type_t; > > ctypeslib translates this as follows: > > class playback_type_t(Structure): > pass > playback_type_t._fields_ = [ > ('zero_1', c_uint, 1), > ('multi_or_random_pgc_title', c_uint, 1), > ('jlc_exists_in_cell_cmd', c_uint, 1), > ('jlc_exists_in_prepost_cmd', c_uint, 1), > ('jlc_exists_in_button_cmd', c_uint, 1), > ('jlc_exists_in_tt_dom', c_uint, 1), > ('chapter_search_or_play', c_uint, 1), > ('title_or_time_play', c_uint, 1), > ] > > It doesn't set _pack_ = 1, but ctypes wouldn't use that to pack the c_uint > bitfield anyway. It's 4 bytes, either way. MSVC agrees, even with #pragma > pack(1). OTOH, with __attribute__((packed)), gcc packs the bitfield into a > single byte. > > The incorrect packing (for gcc) of playback_type_t results in an incorrect > offset for title_set_nr in title_info_t: > > class title_info_t(Structure): > pass > title_info_t._pack_ = 1 > title_info_t._fields_ = [ > ('pb_ty', playback_type_t), > ('nr_of_angles', uint8_t), > ('nr_of_ptts', uint16_t), > ('parental_id', uint16_t), > ('title_set_nr', uint8_t), > ('vts_ttn', uint8_t), > ('title_set_sector', uint32_t), > ] > > As a workaround for the immediate problem, on platforms that use gcc you > can use c_uint8 in playback_type_t instead of c_uint. You'll want to verify > other bitfields as well. I don't know about other compilers on other > platforms. > > Working at the ABI level can be painful. Consider using CFFI's API level > interface instead: > > https://cffi.readthedocs.org > > ---------- > nosy: +eryksun > > _______________________________________ > Python tracker <rep...@bugs.python.org> > <http://bugs.python.org/issue22781> > _______________________________________ > ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue22781> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com