Fix Python 3.12 compatibility for ctypes bitfield structures#82
Merged
leif81 merged 1 commit intoopen-dis:masterfrom Nov 17, 2025
Merged
Fix Python 3.12 compatibility for ctypes bitfield structures#82leif81 merged 1 commit intoopen-dis:masterfrom
leif81 merged 1 commit intoopen-dis:masterfrom
Conversation
This commit resolves compatibility issues with Python 3.12 by fixing
how bitfield structures are created in the ctypes module.
Problem:
Python 3.12 enforced stricter rules for ctypes Structure padding and
alignment. When bitfields used different underlying C types (c_uint8,
c_uint16, c_uint32) for different fields, the compiler inserted
unexpected padding bytes, causing:
- Structure size mismatches
- Binary deserialization failures
- Incorrect PDU parsing
Solution:
Refactored opendis/record/bitfield.py to use a two-pass approach:
1. Calculate total bitfield size across all fields
2. Determine ONE consistent base C type for ALL fields based on total size
3. Apply the same base type to every field in the structure
This ensures no unexpected padding and maintains correct binary
representation across all Python 3.10+ versions.
Changes:
- opendis/record/bitfield.py: Fixed bitfield factory to use consistent
base C types (prevents padding issues in Python 3.12+)
Member
|
Thank-you @khurrameycon I'll take a look. If any other users of the library have comments please feel free to add them here. |
Contributor
|
Looks good to me 👍 |
leif81
approved these changes
Nov 17, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Python 3.12 Compatibility Changes
Summary
This document outlines the changes made to make the
open-dis-pythonlibrary compatible with Python 3.12. The primary issue addressed was ctypes structure padding and alignment, which became stricter in Python 3.12.Problem Statement
When running on Python 3.12, the library was failing due to changes in how
ctypeshandles bitfield structures. Python 3.12 enforced stricter rules about struct padding, requiring all bitfields within a singlectypes.Structureto use the same underlying C type to avoid unexpected padding bytes.Files Changed
1.
opendis/record/bitfield.py(CRITICAL FIX)Lines changed: 119 lines (new) vs 101 lines (old)
Key Changes:
OLD Implementation (Pattern Matching Approach):
Problem: Each field could potentially use a different base type (
c_uint8,c_uint16,c_uint32) based on its individual size. This caused padding issues in Python 3.12 when fields of different sizes were combined in the same structure.NEW Implementation (Two-Pass Approach):
NEW
bitfield()function logic:Solution:
base_ctypebased on the TOTAL size_field()function now takesbase_ctypeas a parameter rather than inferring it from individual field sizes2.
.gitignore(Housekeeping)Changes:
__pycache*→__pycache__*(added missing underscore)*.pyc(explicitly exclude compiled Python files)*.pyo(exclude optimized bytecode files)3. Files NOT Changed
The following files remained unchanged as they were already compatible with Python 3.12:
opendis/dis7.py- Already using modern type annotations (list[...],| None)opendis/DataInputStream.py- Binary I/O, version agnosticopendis/DataOutputStream.py- Binary I/O, version agnosticopendis/PduFactory.py- Factory pattern, compatibleopendis/RangeCoordinates.py- Math utilities, compatiblepyproject.toml- Already requires Python >=3.10Technical Details
Why This Fix Was Necessary
In Python 3.12, the
ctypesmodule became stricter about structure layout. When a bitfield structure contains multiple fields with different underlying C types, the C compiler may insert padding bytes to maintain proper alignment. This caused:The Solution
By ensuring all bitfields use the same underlying C type determined by the TOTAL structure size:
sizeof(Bitfield)equals the expected byte sizeExample
Consider a bitfield with these fields:
OLD (Python 3.11 and earlier):
c_uint8(3 bits <= 8)c_uint16(10 bits > 8, <= 16)NEW (Python 3.12 compatible):
c_uint16c_uint16Testing
The changes maintain backward compatibility with Python 3.10+ while fixing compatibility with Python 3.12.
Impact
This change affects all DIS records that use bitfields, including:
The fix ensures correct binary serialization/deserialization across all Python 3.10+ versions.
Credits
These changes enable the
open-dis-pythonlibrary to work correctly on Python 3.12 while maintaining compatibility with earlier Python 3.10+ versions.