Make the program unaware in compile time of the node types

Using "constructor" attribute
This commit is contained in:
Vftdan 2024-08-15 20:57:17 +02:00
parent 71e04c7f2d
commit 245563ec8b
8 changed files with 77 additions and 17 deletions

View File

@ -12,7 +12,7 @@ CPPFLAGS += $(shell pkg-config --cflags $(DEPS))
LDLIBS += $(shell pkg-config --libs $(DEPS))
INTERP ?=
MAIN = main
OBJS = main.o events.o processing.o graph.o config.o hash_table.o nodes/getchar.o nodes/print.o nodes/evdev.o
OBJS = main.o events.o processing.o graph.o config.o hash_table.o module_registry.o nodes/getchar.o nodes/print.o nodes/evdev.o
all: $(MAIN)

2
defs.h
View File

@ -15,6 +15,8 @@
#define IMPLICIT_CAST(dsttype, srctype, ptr) (((union { typeof(srctype) *src; typeof(dsttype) *dst; }){.src = ptr}).dst)
#define T_ALLOC(count, T) ((T*)calloc(count, sizeof(T)))
#define MODULE_CONSTRUCTOR(name) __attribute__((constructor)) static void name(void)
#define DEBUG_PRINT_VALUE(x, fmt) fprintf(stderr, #x " = " fmt "\n", x); fflush(stderr)
#endif /* end of include guard: DEFS_H_ */

19
main.c
View File

@ -1,14 +1,6 @@
#include "processing.h"
#include "hash_table.h"
#include "nodes/print.h"
#include "nodes/getchar.h"
#include "nodes/evdev.h"
GraphNodeSpecification *node_specifications[] = {
&nodespec_getchar,
&nodespec_print,
&nodespec_evdev,
};
#include "module_registry.h"
int
main(int argc, char ** argv)
@ -42,13 +34,7 @@ main(int argc, char ** argv)
fprintf(stderr, "No node type for node %ld \"%s\"\n", i, loaded_config.nodes.items[i].name);
exit(1);
}
GraphNodeSpecification *spec = NULL;
for (size_t j = 0; j < lengthof(node_specifications); ++j) {
if (strcmp(type_name, node_specifications[j]->name) == 0) {
spec = node_specifications[j];
break;
}
}
GraphNodeSpecification *spec = lookup_graph_node_specification(type_name);
if (!spec) {
fprintf(stderr, "Unknown node type \"%s\" for node %ld \"%s\"\n", type_name, i, loaded_config.nodes.items[i].name);
exit(1);
@ -103,5 +89,6 @@ main(int argc, char ** argv)
io_subscription_list_deinit(&state.wait_output);
io_subscription_list_deinit(&state.wait_input);
destroy_graph_node_specification_registry();
return 0;
}

43
module_registry.c Normal file
View File

@ -0,0 +1,43 @@
#include "module_registry.h"
#include "hash_table.h"
static TYPED_HASH_TABLE(GraphNodeSpecification*) registry;
static bool initialized = false;
static void
ensure_initialized()
{
if (!initialized) {
hash_table_init(&registry, NULL);
initialized = true;
}
}
void
register_graph_node_specification(GraphNodeSpecification * spec)
{
ensure_initialized();
if (!spec->name) {
return;
}
hash_table_insert(&registry, hash_table_key_from_cstr(spec->name), &spec);
}
GraphNodeSpecification *
lookup_graph_node_specification(const char * name)
{
ensure_initialized();
HashTableIndex idx = hash_table_find(&registry, hash_table_key_from_cstr(name));
if (idx < 0) {
return NULL;
}
return registry.value_array[idx];
}
void
destroy_graph_node_specification_registry()
{
ensure_initialized();
hash_table_deinit(&registry);
initialized = false;
}

10
module_registry.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef MODULE_REGISTRY_H_
#define MODULE_REGISTRY_H_
#include "graph.h"
void register_graph_node_specification(GraphNodeSpecification * spec);
GraphNodeSpecification * lookup_graph_node_specification(const char * name);
void destroy_graph_node_specification_registry();
#endif /* end of include guard: MODULE_REGISTRY_H_ */

View File

@ -7,6 +7,7 @@
#include <stdio.h>
#include "evdev.h"
#include "../processing.h"
#include "../module_registry.h"
typedef struct {
GraphNode as_GraphNode;
@ -139,3 +140,8 @@ GraphNodeSpecification nodespec_evdev = (GraphNodeSpecification) {
.register_io = &register_io,
.name = "evdev",
};
MODULE_CONSTRUCTOR(init)
{
register_graph_node_specification(&nodespec_evdev);
}

View File

@ -2,6 +2,7 @@
#include <unistd.h>
#include "getchar.h"
#include "../processing.h"
#include "../module_registry.h"
typedef struct {
GraphNode as_GraphNode;
@ -98,3 +99,8 @@ GraphNodeSpecification nodespec_getchar = (GraphNodeSpecification) {
.register_io = &register_io,
.name = "getchar",
};
MODULE_CONSTRUCTOR(init)
{
register_graph_node_specification(&nodespec_getchar);
}

View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include "print.h"
#include "../module_registry.h"
static bool
handle_event(EventPositionBase * self, EventNode * event)
@ -59,3 +60,8 @@ GraphNodeSpecification nodespec_print = (GraphNodeSpecification) {
.register_io = NULL,
.name = "print",
};
MODULE_CONSTRUCTOR(init)
{
register_graph_node_specification(&nodespec_print);
}