static void create_seconds(void) { const struct sol_flow_node_type **type; struct sol_flow_node_named_options named_opts = {}; const char *strv_opts[] = { "send_initial_packet=1", NULL }; struct sol_flow_node_options *opts; int err; err = sol_flow_get_node_type("wallclock", SOL_FLOW_NODE_TYPE_WALLCLOCK_SECOND, &type); if (err < 0) { fputs("could not find type: wallclock/second\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } seconds_port_enabled = sol_flow_node_find_port_in(*type, "ENABLED"); if (seconds_port_enabled == UINT16_MAX) { fputs("ERROR: couldn't find ouput port by name: ENABLED\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } seconds_port_out = sol_flow_node_find_port_out(*type, "OUT"); if (seconds_port_out == UINT16_MAX) { fputs("ERROR: couldn't find ouput port by name: OUT\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } err = sol_flow_node_named_options_init_from_strv(&named_opts, *type, strv_opts); if (err < 0) { fputs("could not parse options for wallclock/second\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } err = sol_flow_node_options_new(*type, &named_opts, &opts); sol_flow_node_named_options_fini(&named_opts); if (err < 0) { fputs("could not create options for wallclock/second\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } seconds = sol_flow_single_new("seconds", *type, opts, SOL_FLOW_SINGLE_CONNECTIONS(seconds_port_enabled), SOL_FLOW_SINGLE_CONNECTIONS(seconds_port_out), on_seconds_packet, NULL); sol_flow_node_options_del(*type, opts); }
static void startup(void) { const struct sol_flow_node_type **console_type; if (sol_flow_get_node_type("console", SOL_FLOW_NODE_TYPE_CONSOLE, &console_type) < 0) return; /* * Since these symbols will be relocated in runtime, we can't * initialize them in the vector initialization, we must assign * them in runtime. */ nodes[0 /* reader */].type = SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_READER; nodes[1 /* logic */].type = SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_LOGIC; nodes[2 /* writer */].type = SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_WRITER; nodes[3 /* console */].type = *console_type; flow = sol_flow_static_new(NULL, nodes, conns); }
static void create_minutes(void) { const struct sol_flow_node_type **type; struct sol_flow_node_named_options named_opts = {}; const char *strv_opts[] = { "send_initial_packet=1", NULL }; struct sol_flow_node_options *opts; int err; /* Resolves the type based on its name. This will take care of * built-in modules and external modules, loading on demand as * required. This macro also handles static-compiles, so the * second parameter is the C symbol to be used in such case. */ err = sol_flow_get_node_type("wallclock", SOL_FLOW_NODE_TYPE_WALLCLOCK_MINUTE, &type); if (err < 0) { fputs("could not find type: wallclock/minute\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } /* For efficiency matters Soletta doesn't work with port names, * rather using port indexes. If * SOL_FLOW_NODE_TYPE_DESCRIPTION_ENABLED, then we can resolve * strings to numbers, otherwise it is required to check the port * numbers, which are often available in the header file such as * sol-flow/wallclock.h such as * SOL_FLOW_NODE_TYPE_WALLCLOCK_MINUTE__OUT__OUT. */ minutes_port_enabled = sol_flow_node_find_port_in(*type, "ENABLED"); if (minutes_port_enabled == UINT16_MAX) { fputs("ERROR: couldn't find ouput port by name: ENABLED\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } minutes_port_out = sol_flow_node_find_port_out(*type, "OUT"); if (minutes_port_out == UINT16_MAX) { fputs("ERROR: couldn't find ouput port by name: OUT\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } /* wallclock/minute takes a boolean option send_initial_packet. * We have couple of options to create it: * * 1 - include sol-flow/wallclock.h, declare a variable of type * struct sol_flow_node_type_wallclock_minute_options and fill * its members. This requires sol-flow/wallclock.h to be * avaiable, but is more efficient since goes straight to the * point, no parsing or memory allocations. It would look * like: * * #include <sol-flow/wallclock.h> * * struct sol_flow_node_type_wallclock_minute_options opts = * SOL_FLOW_NODE_TYPE_WALLCLOCK_MINUTE_OPTIONS_DEFAULTS( * .send_initial_packet = true); * * 2 - access type->options_size, * type->default_options and * type->description->options and manually * create the structure in runtime. This demands * SOL_FLOW_NODE_TYPE_DESCRIPTION_ENABLED, but may be useful * when converting from a different representation, like a * language binding such as JavaScript or Python where one can * get an object, hashmap or dictionary and convert straight * to the C structure needed by the flow node type. * * 3 - use helper sol_flow_node_named_options_init_from_strv() and * sol_flow_node_options_new(), giving it an array of * "key=value" strings. It will do the work described in #2 * for us, thus also depends on * SOL_FLOW_NODE_TYPE_DESCRIPTION_ENABLED. * * We'll use approach #3 since it is simpler. Language bindings * should go with option #2 and those that want to squeeze the * size and get performance should consider #1. */ err = sol_flow_node_named_options_init_from_strv(&named_opts, *type, strv_opts); if (err < 0) { fputs("could not parse options for wallclock/minute\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } /* convert the named options in the actual options structure */ err = sol_flow_node_options_new(*type, &named_opts, &opts); sol_flow_node_named_options_fini(&named_opts); if (err < 0) { fputs("could not create options for wallclock/minute\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } /* Build the single node wrapping the wanted 'wallclock/minute'. * For most matters the single node behaves like the inner node, * it will copy the descriptions and options. * * The difference is that if you call sol_flow_send_packet() on * its input ports, it will forward the packet to the inner * node. Likewise, packets originated at the outgoing ports of the * inner node will be delivered through the process callback * (on_packet()) provided to the single node. * * Note that ports you want to send (in) or receive (out) packets * must be connected with the connected_ports_in and * connected_ports_out parameters, or later with * sol_flow_single_port_in_connect() and * sol_flow_single_port_out_connect(). */ minutes = sol_flow_single_new("minutes", *type, opts, SOL_FLOW_SINGLE_CONNECTIONS(minutes_port_enabled), SOL_FLOW_SINGLE_CONNECTIONS(minutes_port_out), on_minutes_packet, NULL); sol_flow_node_options_del(*type, opts); }