[PATCH] libubus: Add UBUS_OBJECT() macro

Karsten Sperling ksperling at apple.com
Mon Jun 8 17:14:03 PDT 2026


Especially in C++ (where depending on compiler settings, field order and
completeness is enforced), initializing an ubus_object is a little tedious.
Introduce an UBUS_OBJECT() macro that can be used to initialize an
ubus_object with a name and type.

The n_methods field is set to -1 to signal to ubus_add_object() that
methods should be copied from the object type (if they haven't been changed
in the meantime). Copying them from the type in UBUS_OBJECT() directly is
not desirable because it would make for a non-constant initializer.

The cpptest now compiles with c++20 so the test can enforce constinit.

Signed-off-by: Karsten Sperling <ksperling at apple.com>
---
 examples/server.c        |  8 ++------
 libubus-obj.c            |  5 +++++
 libubus.h                | 13 +++++++++++++
 tests/CMakeLists.txt     |  2 +-
 tests/test-cplusplus.cpp |  5 +++--
 5 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/examples/server.c b/examples/server.c
index 0913fff..42ce3f7 100644
--- a/examples/server.c
+++ b/examples/server.c
@@ -204,12 +204,8 @@ static const struct ubus_method test_methods[] = {
 static struct ubus_object_type test_object_type =
 	UBUS_OBJECT_TYPE("test", test_methods);
 
-static struct ubus_object test_object = {
-	.name = "test",
-	.type = &test_object_type,
-	.methods = test_methods,
-	.n_methods = ARRAY_SIZE(test_methods),
-};
+static struct ubus_object test_object =
+	UBUS_OBJECT("test", test_object_type);
 
 static void server_main(void)
 {
diff --git a/libubus-obj.c b/libubus-obj.c
index 4a56110..1fb2ff6 100644
--- a/libubus-obj.c
+++ b/libubus-obj.c
@@ -233,6 +233,11 @@ int ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj)
 			return UBUS_STATUS_INVALID_ARGUMENT;
 	}
 
+	if (obj->n_methods < 0 && obj->type) { /* initialized via UBUS_OBJECT() */
+		obj->methods = obj->type->methods;
+		obj->n_methods = obj->type->n_methods;
+	}
+
 	if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_ADD_OBJECT, 0) < 0)
 		return UBUS_STATUS_INVALID_ARGUMENT;
 
diff --git a/libubus.h b/libubus.h
index 4f33339..787ea4d 100644
--- a/libubus.h
+++ b/libubus.h
@@ -108,6 +108,19 @@ typedef bool (*ubus_new_object_handler_t)(struct ubus_context *ctx, struct ubus_
 #define UBUS_TAG_ADMIN		(1ul << 1)
 #define UBUS_TAG_PRIVATE	(1ul << 2)
 
+#define UBUS_OBJECT(_name, _type)			\
+	{						\
+		.avl = {},				\
+		.name = _name,				\
+		.id = 0,				\
+		.path = NULL,				\
+		.type = &(_type),			\
+		.subscribe_cb = NULL,			\
+		.has_subscribers = false,		\
+		.methods = NULL,			\
+		.n_methods = -1				\
+	}
+
 struct ubus_method {
 	const char *name;
 	ubus_handler_t handler;
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f0900e9..14ab660 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -22,7 +22,7 @@ FOREACH(test_case ${test_cases})
 ENDFOREACH(test_case)
 
 ENABLE_LANGUAGE(CXX)
-ADD_COMPILE_OPTIONS($<$<COMPILE_LANGUAGE:CXX>:-std=gnu++11>)
+ADD_COMPILE_OPTIONS($<$<COMPILE_LANGUAGE:CXX>:-std=gnu++20>)
 ADD_UNIT_TEST_CPP(test-cplusplus)
 ADD_TEST(NAME cplusplus COMMAND test-cplusplus)
 
diff --git a/tests/test-cplusplus.cpp b/tests/test-cplusplus.cpp
index 89c5ffb..441a913 100644
--- a/tests/test-cplusplus.cpp
+++ b/tests/test-cplusplus.cpp
@@ -25,10 +25,11 @@ constexpr ubus_method test_methods[] = {
 	UBUS_METHOD_TAG_NOARG("hello5", handler, UBUS_TAG_STATUS),
 };
 
-constexpr ubus_object_type test_object_type = UBUS_OBJECT_TYPE("test", test_methods);
+constinit ubus_object_type test_object_type = UBUS_OBJECT_TYPE("test", test_methods);
+constinit ubus_object test_object = UBUS_OBJECT("testobj", test_object_type);
 
 int main()
 {
-	(void) test_object_type;
+	(void) test_object;
 	return 0;
 }
-- 
2.50.1 (Apple Git-155)



More information about the openwrt-devel mailing list