diff --git a/src/controller/python/chip/native/__init__.py b/src/controller/python/chip/native/__init__.py index 2528aeca32bd1b..1256748dc5622d 100644 --- a/src/controller/python/chip/native/__init__.py +++ b/src/controller/python/chip/native/__init__.py @@ -16,6 +16,7 @@ import ctypes import enum +import functools import glob import os import platform @@ -146,21 +147,31 @@ def __ne__(self, other): return not self == other -PostAttributeChangeCallback = ctypes.CFUNCTYPE( +c_PostAttributeChangeCallback = ctypes.CFUNCTYPE( None, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint8, ctypes.c_uint16, - # TODO: This should be a pointer to uint8_t, but ctypes does not provide - # such a type. The best approximation is c_char_p, however, this - # requires the caller to pass NULL-terminate C-string which might - # not be the case here. - ctypes.c_char_p, + ctypes.POINTER(ctypes.c_char), ) +def PostAttributeChangeCallback(func): + @functools.wraps(func) + def wrapper( + endpoint: int, + clusterId: int, + attributeId: int, + xx_type: int, + size: int, + value: ctypes.POINTER(ctypes.c_char), + ): + return func(endpoint, clusterId, attributeId, xx_type, size, value[:size]) + return c_PostAttributeChangeCallback(wrapper) + + def FindNativeLibraryPath(library: Library) -> str: """Find the native CHIP dll/so path.""" @@ -234,7 +245,7 @@ def _GetLibraryHandle(lib: Library, expectAlreadyInitialized: bool) -> _Handle: [ctypes.POINTER(PyChipError), ctypes.c_char_p, ctypes.c_uint32]) elif lib == Library.SERVER: setter.Set("pychip_server_native_init", PyChipError, []) - setter.Set("pychip_server_set_callbacks", None, [PostAttributeChangeCallback]) + setter.Set("pychip_server_set_callbacks", None, [c_PostAttributeChangeCallback]) handle = _nativeLibraryHandles[lib] if expectAlreadyInitialized and not handle.initialized: diff --git a/src/controller/python/chip/server/__init__.py b/src/controller/python/chip/server/__init__.py index 8280ec09186790..b42cc40309903b 100644 --- a/src/controller/python/chip/server/__init__.py +++ b/src/controller/python/chip/server/__init__.py @@ -17,11 +17,20 @@ import ctypes from chip import native -from chip.native import PostAttributeChangeCallback +from chip.native import PostAttributeChangeCallback, c_PostAttributeChangeCallback +__all__ = [ + "GetLibraryHandle", + "PostAttributeChangeCallback", +] -def GetLibraryHandle(cb: PostAttributeChangeCallback) -> ctypes.CDLL: - """Get a memoized handle to the chip native code dll.""" + +def GetLibraryHandle(cb: c_PostAttributeChangeCallback) -> ctypes.CDLL: + """Get a memoized handle to the chip native code dll. + + Args: + cb: A callback decorated by PostAttributeChangeCallback decorator. + """ handle = native._GetLibraryHandle(native.Library.SERVER, False) if not handle.initialized: