From 15f3bf10b853b0327a65196713e8f63473b07744 Mon Sep 17 00:00:00 2001 From: Luca Toniolo <10792599+grandixximo@users.noreply.github.com> Date: Sat, 19 Sep 2026 20:09:32 +1000 Subject: [PATCH] halmodule: fix inverted float to bool, unterminated RTType table, missing PyErr_Format argument from_python(PyObject *, bool *) set the bool to true when the float was 0.0 and false otherwise, so writing 1.0 to a bool pin or param cleared it and writing 0.0 set it. The comment above it already stated the intended rule; the comparison is now "!= 0.0". halenum_rt_members[] had no empty terminator, so halenum_build("RTType", ...) kept reading past the end of the array until it found a NULL name in whatever followed in .rodata. Whether the enum built correctly depended on the memory layout of the build. check_port() passed two arguments to a format with three conversions, so the "Pin type not HAL_PORT" message printed the type where the pin name belongs and read garbage for the type. tests/halmodule/comp-set-get now writes floats and ints into a bool param and checks what comes back. --- src/hal/halmodule.cc | 5 +++-- tests/halmodule/comp-set-get/expected | 5 +++++ tests/halmodule/comp-set-get/test.py | 7 +++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/hal/halmodule.cc b/src/hal/halmodule.cc index 3f581d7de4b..9c354a30aa8 100644 --- a/src/hal/halmodule.cc +++ b/src/hal/halmodule.cc @@ -147,7 +147,7 @@ bool from_python(PyObject *o, bool *b) if(PyFloat_Check(o)) { // Floating point is false *only* when it is 0.0 double v = PyFloat_AsDouble(o); - *b = 0.0 == v; + *b = 0.0 != v; return true; } @@ -913,7 +913,7 @@ static bool check_port(const pyhalitem *item, const char *pfx) return false; } if(item->pin.type != HAL_PORT) { - PyErr_Format(PyExc_RuntimeError, "%s: %s: Pin type not HAL_PORT but '%d'", pfx, (int)item->pin.type); + PyErr_Format(PyExc_RuntimeError, "%s: %s: Pin type not HAL_PORT but '%d'", pfx, item->name, (int)item->pin.type); return false; } return true; @@ -2239,6 +2239,7 @@ static const halenum_member_t halenum_rt_members[] = { {"LXRT", REALTIME_TYPE_LXRT}, {"XENOMAI", REALTIME_TYPE_XENOMAI}, {"XENOMAI_EVL", REALTIME_TYPE_XENOMAI_EVL}, + {} }; // Build an enum.IntEnum subclass from a member table. The class claims diff --git a/tests/halmodule/comp-set-get/expected b/tests/halmodule/comp-set-get/expected index 37c7b48be8d..34009b990ec 100644 --- a/tests/halmodule/comp-set-get/expected +++ b/tests/halmodule/comp-set-get/expected @@ -35,3 +35,8 @@ pincheck s True True True pincheck param False True True set u 0 0 set u -1 fail +set param 0.0 ok +set param 1.0 ok +set param -0.5 True +set param 0 ok +set param 2 True diff --git a/tests/halmodule/comp-set-get/test.py b/tests/halmodule/comp-set-get/test.py index 46d6d36b0f3..9a10f2a60e3 100755 --- a/tests/halmodule/comp-set-get/test.py +++ b/tests/halmodule/comp-set-get/test.py @@ -88,6 +88,13 @@ def pin_validate(i, t, d): try_set_pin(pu, 0) try_set_pin(pu, -1) + + # A float into a bool is false only when it is 0.0 + try_set("param", 0.0) + try_set("param", 1.0) + try_set("param", -0.5) + try_set("param", 0) + try_set("param", 2) except: import traceback print("Exception: {}".format(traceback.format_exc()))