This does NOT change the module API/ABI in any way.
uv_stop(uv_default_loop());
}
-/** Register module properties in Lua environment */
+/** Register module properties in Lua environment, if any. */
static int register_properties(struct engine *engine, struct kr_module *module)
{
+ if (!module->config && !module->props) {
+ return kr_ok();
+ }
lua_newtable(engine->L);
if (module->config != NULL) {
REGISTER_MODULE_CALL(engine->L, module, module->config, "config");
}
- for (struct kr_prop *p = module->props; p && p->name; ++p) {
- if (p->cb != NULL && p->name != NULL) {
+
+ const struct kr_prop *p = module->props == NULL ? NULL : module->props();
+ for (; p && p->name; ++p) {
+ if (p->cb != NULL) {
REGISTER_MODULE_CALL(engine->L, module, p->cb, p->name);
}
}
}
}
- /* Register properties */
- if (module->props || module->config) {
- return register_properties(engine, module);
- }
-
- return kr_ok();
+ return register_properties(engine, module);
}
int engine_unregister(struct engine *engine, const char *name)
#define LIBEXT ".so"
#endif
-/** Check ABI version, return error on mismatch. */
-#define ABI_CHECK(m, prefix, symname, required) do { \
- module_api_cb *_api = NULL; \
- *(void **) (&_api) = load_symbol((m)->lib, (prefix), (symname)); \
- if (_api == NULL) { \
- return kr_error(ENOENT); \
- } \
- if (_api() != (required)) { \
- return kr_error(ENOTSUP); \
- } \
-} while (0)
-
-/** Load ABI by symbol names. */
-#define ABI_LOAD(m, prefix, s_init, s_deinit, s_config, s_layer, s_prop) do { \
- module_prop_cb *module_prop = NULL; \
- *(void **) (&(m)->init) = load_symbol((m)->lib, (prefix), (s_init)); \
- *(void **) (&(m)->deinit) = load_symbol((m)->lib, (prefix), (s_deinit)); \
- *(void **) (&(m)->config) = load_symbol((m)->lib, (prefix), (s_config)); \
- *(void **) (&(m)->layer) = load_symbol((m)->lib, (prefix), (s_layer)); \
- *(void **) (&module_prop) = load_symbol((m)->lib, (prefix), (s_prop)); \
- if (module_prop != NULL) { \
- (m)->props = module_prop(); \
- } \
-} while(0)
/** Load prefixed symbol. */
static void *load_symbol(void *lib, const char *prefix, const char *name)
}
}
/* Load dynamic library module */
- auto_free char *module_prefix = kr_strcatdup(2, module->name, "_");
- ABI_CHECK(module, module_prefix, "api", api_required);
- ABI_LOAD(module, module_prefix, "init", "deinit", "config", "layer", "props");
+ auto_free char *m_prefix = kr_strcatdup(2, module->name, "_");
+
+ /* Check ABI version, return error on mismatch. */
+ module_api_cb *api = load_symbol(module->lib, m_prefix, "api");
+ if (api == NULL) {
+ return kr_error(ENOENT);
+ }
+ if (api() != api_required) {
+ return kr_error(ENOTSUP);
+ }
+
+ /* Load ABI by symbol names. */
+ #define ML(symname) module->symname = \
+ load_symbol(module->lib, m_prefix, #symname)
+ ML(init);
+ ML(deinit);
+ ML(config);
+ ML(layer);
+ ML(props);
+ #undef ML
+
return kr_ok();
}
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/** @file module API definition and functions for (un)loading modules. */
+
#pragma once
#include "lib/defines.h"
#include "lib/utils.h"
#include "lib/layer.h"
-/*
- * Forward decls
- */
struct kr_module;
struct kr_prop;
-/*
- * API definition.
- * @cond internal
+
+/**
+ * Export module API version (place this at the end of your module).
+ *
+ * @param module module name (f.e. hints)
*/
-typedef uint32_t (module_api_cb)(void);
-typedef int (module_init_cb)(struct kr_module *);
-typedef int (module_deinit_cb)(struct kr_module *);
-typedef int (module_config_cb)(struct kr_module *, const char *);
-typedef const kr_layer_api_t* (module_layer_cb)(struct kr_module *);
-typedef struct kr_prop *(module_prop_cb)(void);
-typedef char *(kr_prop_cb)(void *, struct kr_module *, const char *);
+#define KR_MODULE_EXPORT(module) \
+ KR_EXPORT uint32_t module ## _api() { return KR_MODULE_API; }
#define KR_MODULE_API ((uint32_t) 0x20161108)
-/* @endcond */
+
+typedef uint32_t (module_api_cb)(void);
+
/**
- * Module property (named callable).
- * A module property has a free-form JSON output (and optional input).
+ * Module representation.
+ *
+ * The five symbols (init, ...) may be defined by the module as name_init(), etc;
+ * all are optional and missing symbols are represented as NULLs;
*/
-struct kr_prop {
- kr_prop_cb *cb;
- const char *name;
- const char *info;
+struct kr_module {
+ char *name;
+
+ /** Constructor. Called after loading the module. @return error code. */
+ int (*init)(struct kr_module *self);
+ /** Destructor. Called before unloading the module. @return error code. */
+ int (*deinit)(struct kr_module *self);
+ /** Configure with encoded JSON (NULL if missing). @return error code. */
+ int (*config)(struct kr_module *self, const char *input);
+ /** Get a pointer to packet processing API specs. See docs on that type. */
+ const kr_layer_api_t * (*layer)(struct kr_module *self);
+ /** Get a pointer to list of properties, terminated by { NULL, NULL, NULL }. */
+ const struct kr_prop * (*props)(void);
+
+ void *lib; /**< Shared library handle or RTLD_DEFAULT */
+ void *data; /**< Custom data context. */
};
/**
- * Module representation.
+ * Module property callback. Input and output is passed via a JSON encoded in a string.
+ *
+ * @param env pointer to the lua engine, i.e. struct engine *env (TODO: explicit type)
+ * @param input parameter (NULL if missing/nil on lua level)
+ * @return a free-form JSON output (malloc-ated)
*/
-struct kr_module {
- char *name; /**< Name. */
- module_init_cb *init; /**< Constructor */
- module_deinit_cb *deinit; /**< Destructor */
- module_config_cb *config; /**< Configuration */
- module_layer_cb *layer; /**< Layer getter */
- struct kr_prop *props; /**< Properties */
- void *lib; /**< Shared library handle or RTLD_DEFAULT */
- void *data; /**< Custom data context. */
+typedef char *(kr_prop_cb)(void *env, struct kr_module *self, const char *input);
+
+/**
+ * Module property (named callable).
+ */
+struct kr_prop {
+ kr_prop_cb *cb;
+ const char *name;
+ const char *info;
};
+
/**
* Load module instance into memory.
*
KR_EXPORT
void kr_module_unload(struct kr_module *module);
-/**
- * Export module API version (place this at the end of your module).
- *
- * @param module module name (f.e. hints)
- */
-#define KR_MODULE_EXPORT(module) \
- KR_EXPORT uint32_t module ## _api() { return KR_MODULE_API; }
static char *callprop(struct kr_module *module, const char *prop, const char *input, void *env)
{
- if (!module || !prop) {
+ if (!module || !module->props || !prop) {
return NULL;
}
- for (struct kr_prop *p = module->props; p && p->name; ++p) {
+ for (const struct kr_prop *p = module->props(); p && p->name; ++p) {
if (p->cb != NULL && strcmp(p->name, prop) == 0) {
return p->cb(env, module, input);
}