[Buildroot] [PATCH 3/7] package/libcec: fix build with swig >= 4.5.0
Bernd Kuhls
bernd at kuhls.net
Sat Sep 5 12:20:35 UTC 2026
Patch 0002 fixes the build with swig >= 4.5.0.
Patch 0001 is needed to cleanly apply patch 0002.
Signed-off-by: Bernd Kuhls <bernd at kuhls.net>
---
...DeviceLanguage-accepts-3-char-ISO-co.patch | 66 ++++++++++++++++
...Python-wrapper-against-SWIG-4.5-whic.patch | 78 +++++++++++++++++++
2 files changed, 144 insertions(+)
create mode 100644 package/libcec/0001-fixed-Python-strDeviceLanguage-accepts-3-char-ISO-co.patch
create mode 100644 package/libcec/0002-fixed-build-the-Python-wrapper-against-SWIG-4.5-whic.patch
diff --git a/package/libcec/0001-fixed-Python-strDeviceLanguage-accepts-3-char-ISO-co.patch b/package/libcec/0001-fixed-Python-strDeviceLanguage-accepts-3-char-ISO-co.patch
new file mode 100644
index 0000000000..e2a86e1f7e
--- /dev/null
+++ b/package/libcec/0001-fixed-Python-strDeviceLanguage-accepts-3-char-ISO-co.patch
@@ -0,0 +1,66 @@
+From f53490e23037f17b68043f5e1ff2f4378d227d56 Mon Sep 17 00:00:00 2001
+From: Lars Op den Kamp <lars at opdenkamp.eu>
+Date: Mon, 13 Jul 2026 15:24:27 +0200
+Subject: [PATCH] fixed: Python strDeviceLanguage accepts 3-char ISO codes
+ (SWIG char[3] typemap)
+
+The SWIG default char[ANY] setter uses SWIG_AsCharArray, which reserves a
+byte for a NUL terminator. strDeviceLanguage is a raw, non-terminated
+char[3] holding a 3-character ISO 639-2 code, so a valid 3-char value needs
+4 bytes and overflowed the buffer, raising a TypeError; only 2-char codes
+fit. Add member-name-scoped in/memberin typemaps that copy the raw bytes
+(str or bytes) so 3-char codes assign correctly. Scoped by name so the
+NUL-terminated strDeviceName keeps the default behaviour.
+
+Upstream: https://github.com/Pulse-Eight/libcec/commit/f53490e23037f17b68043f5e1ff2f4378d227d56
+
+Signed-off-by: Bernd Kuhls <bernd at kuhls.net>
+---
+ src/libcec/libcec.i | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/src/libcec/libcec.i b/src/libcec/libcec.i
+index a01f9afc..520ff7af 100644
+--- a/src/libcec/libcec.i
++++ b/src/libcec/libcec.i
+@@ -15,6 +15,37 @@
+ $result = PyString_FromString($1.name);
+ }
+
++/////// libcec_configuration::strDeviceLanguage ///////
++// strDeviceLanguage is a raw, fixed-size char[3] that is NOT NUL-terminated (a
++// 3-character ISO 639-2 code). SWIG's default char[ANY] setter reserves a byte
++// for a terminator, so a valid 3-char code needs 4 bytes and overflows the
++// buffer, raising a TypeError; only 2-char codes fit. Copy the raw bytes
++// instead (accepting str or bytes), scoped to this member by name so the
++// NUL-terminated strDeviceName keeps the default behaviour.
++%typemap(in) char strDeviceLanguage[ANY] (char temp[$1_dim0]) {
++ char *cptr = 0; size_t csize = 0; int alloc = SWIG_OLDOBJ;
++ int res = SWIG_AsCharPtrAndSize($input, &cptr, &csize, &alloc);
++ if (!SWIG_IsOK(res)) {
++ %argument_fail(res, "char [$1_dim0]", $symname, $argnum);
++ }
++ {
++ /* csize counts the trailing NUL; strDeviceLanguage stores no terminator */
++ size_t slen = (csize > 0) ? csize - 1 : 0;
++ if (slen > (size_t)($1_dim0)) {
++ if (alloc == SWIG_NEWOBJ) %delete_array(cptr);
++ %argument_fail(SWIG_ValueError, "char [$1_dim0]", $symname, $argnum);
++ }
++ memset(temp, 0, $1_dim0);
++ if (slen) memcpy(temp, cptr, slen);
++ }
++ $1 = temp;
++ if (alloc == SWIG_NEWOBJ) %delete_array(cptr);
++}
++
++%typemap(memberin) char strDeviceLanguage[ANY] {
++ memcpy($1, $input, $1_dim0 * sizeof(char));
++}
++
+ /////// replace operator[]() ///////
+
+ // CEC::cec_datapacket::operator[]()
+--
+2.47.3
+
diff --git a/package/libcec/0002-fixed-build-the-Python-wrapper-against-SWIG-4.5-whic.patch b/package/libcec/0002-fixed-build-the-Python-wrapper-against-SWIG-4.5-whic.patch
new file mode 100644
index 0000000000..351091e17d
--- /dev/null
+++ b/package/libcec/0002-fixed-build-the-Python-wrapper-against-SWIG-4.5-whic.patch
@@ -0,0 +1,78 @@
+From 55f3443559b0b32a1d7194e424727575faf6f7d4 Mon Sep 17 00:00:00 2001
+From: Lars Op den Kamp <lars at opdenkamp.eu>
+Date: Fri, 31 Jul 2026 14:46:27 +0200
+Subject: [PATCH] fixed: build the Python wrapper against SWIG 4.5, which
+ removed the Python 2 compatibility macros
+
+SWIG 4.5 dropped the PyInt_*/PyString_* macros that pyhead.swg used to define
+for user typemaps. Two places here relied on them.
+
+The callback return handling keeps a PY_MAJOR_VERSION guard rather than moving
+to the Python 3 API outright, because the x86 Windows build still targets
+Python 2 for the EventGhost plugin. A Python 2 int is a PyIntObject, not a
+PyLongObject, so an unguarded PyLong_Check would compile there and then
+silently read every commandHandler and menuStateChanged return value as 0 - the
+one thing those callbacks exist to report. SWIG never reads SwigHelper.h, so
+the C preprocessor makes the choice and the file is SWIG-version independent.
+
+The cec_osd_name out-typemap is deleted rather than fixed, because it is dead:
+GetDeviceOSDName returns std::string, and cec_osd_name only survives as an out
+parameter in the C API, which is not wrapped. It could not have compiled if it
+ever did fire - cec_osd_name is a typedef for char[14], so the $1.name it
+dereferences has no member to name. Removing it leaves the generated wrapper
+byte-for-byte identical.
+
+Verified by preprocessing SwigHelper.h against both Python 3.10 and Python 2.7:
+Python 3 resolves to PyObject_CallObject/PyLong_AsLong with no removed macro
+surviving anywhere, Python 2 to PyEval_CallObject/PyInt_AsLong.
+
+closes #726
+
+Upstream: https://github.com/Pulse-Eight/libcec/commit/55f3443559b0b32a1d7194e424727575faf6f7d4
+
+Signed-off-by: Bernd Kuhls <bernd at kuhls.net>
+---
+ src/libcec/SwigHelper.h | 9 +++++++++
+ src/libcec/libcec.i | 4 ----
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/src/libcec/SwigHelper.h b/src/libcec/SwigHelper.h
+index 3c40fc87..0752acb2 100644
+--- a/src/libcec/SwigHelper.h
++++ b/src/libcec/SwigHelper.h
+@@ -137,8 +137,17 @@ namespace CEC
+ Py_DECREF(arglist);
+ if (!!result)
+ {
++ /** SWIG 4.5 removed the PyInt_* compatibility macros it used to define
++ for Python 3, so call the version-appropriate API directly. Note that
++ a Python 2 int is a PyIntObject, not a PyLongObject, so PyLong_Check
++ would silently reject it there. */
++ #if (PY_MAJOR_VERSION < 3)
+ if (PyInt_Check(result))
+ retval = (int)PyInt_AsLong(result);
++ #else // (PY_MAJOR_VERSION >= 3)
++ if (PyLong_Check(result))
++ retval = (int)PyLong_AsLong(result);
++ #endif
+ Py_XDECREF(result);
+ }
+ }
+diff --git a/src/libcec/libcec.i b/src/libcec/libcec.i
+index 520ff7af..0d757aa1 100644
+--- a/src/libcec/libcec.i
++++ b/src/libcec/libcec.i
+@@ -11,10 +11,6 @@
+
+ %ignore *::operator=;
+
+-%typemap(out) CEC::cec_osd_name {
+- $result = PyString_FromString($1.name);
+-}
+-
+ /////// libcec_configuration::strDeviceLanguage ///////
+ // strDeviceLanguage is a raw, fixed-size char[3] that is NOT NUL-terminated (a
+ // 3-character ISO 639-2 code). SWIG's default char[ANY] setter reserves a byte
+--
+2.47.3
+
--
2.47.3
More information about the buildroot
mailing list