-
-
Notifications
You must be signed in to change notification settings - Fork 104
submit_event() always returns False on Windows (MSVC) — IS_ENABLED() macro mismatch #289
Description
Hi, I had an issue trying to make a test cardreader PD in python on Windows with submit_event(). After bashing my head into a wall with Claude for a while I managed to fix the issue.
Full transparency: I'm very much out of my depth here, so here is Claude's synopsis on what went wrong and how to fix it. Apologies for the AI slop.
Summary
osdp_pd_submit_event() silently fails on Windows builds because the IS_ENABLED() macro evaluates incorrectly under MSVC's legacy preprocessor, creating a code path mismatch between the Python C extension and the core library.
Root Cause
libosdp uses a Linux kernel-style IS_ENABLED() macro (from c-utils/include/utils/utils.h):
#define __IS_ENABLED1(x) __IS_ENABLED2(__XXXX ## x)
#define __XXXX1 __YYYY,
#define __IS_ENABLED2(y) __IS_ENABLED3(y 1, 0)
#define __IS_ENABLED3(_i, val, ...) val
#define IS_ENABLED(x) __IS_ENABLED1(x)
This relies on token-pasting:
When OPT_OSDP_APP_OWNED_QUEUE_DATA=1, __XXXX ## 1 → __XXXX1 → expands to __YYYY, which injects a comma and makes __IS_ENABLED3 return 1.
MSVC's legacy preprocessor does not expand macro arguments before ## token pasting like GCC/Clang do.
Result:
IS_ENABLED(OPT_OSDP_APP_OWNED_QUEUE_DATA) evaluates to 0 on MSVC even when the flag is defined.
This creates a mismatch:
So:
osdp_pd_submit_event()
-> pd_event_alloc()
-> returns NULL
-> return -1
Python wrapper converts this to:
PeripheralDevice.submit_event(...) -> False
No events are queued or sent.
Impact
On Windows:
-
PeripheralDevice.submit_event()always returnsFalse - No card reads / keypad / manufacturer events sent
-
PD replies to POLL with
ACK (0x40)instead ofREPLY_RAW (0x50) - Appears as if event submission is broken
Affected Versions
- libosdp 3.2.0 (PyPI Windows wheel)
-
Any build using
IS_ENABLED()with MSVC legacy preprocessor
Fix Options
Option A — Compiler flag (workaround)
Enable conformant MSVC preprocessor:
set CL=/Zc:preprocessor
pip install --no-binary :all: --no-cache-dir libosdp==3.2.0
This fixes IS_ENABLED() evaluation.
Option B — Code fix (preferred)
Make both files use identical guards.
In src/osdp_pd.c:
// Before
if (IS_ENABLED(OPT_OSDP_APP_OWNED_QUEUE_DATA)) {
// After
#ifdef OPT_OSDP_APP_OWNED_QUEUE_DATA
This matches python/osdp_sys/pd.c and avoids macro dependence.
Option C — Disable flag (alternate path)
Requires full Git source (PyPI tarball missing slab.c):
set OPT_OSDP_APP_OWNED_QUEUE_DATA=off
pip install "git+https://github.com/goToMain/libosdp@v3.2.0#egg=libosdp&subdirectory=python"
Additional Issue
PyPI source tarball for v3.2.0 is missing:
vendor/utils/src/slab.c
When building with:
OPT_OSDP_APP_OWNED_QUEUE_DATA=off
Build fails:
RuntimeError: Path 'vendor\utils/src/slab.c' does not exist
Full Git clone (with submodules) is required.
Suggested Resolution
Either:
-
Replace
IS_ENABLED()with#ifdefinsrc/osdp_pd.c -
Or force
/Zc:preprocessorin Windows build flags - Or remove mixed guard usage across compilation units
This restores correct event submission on Windows.