Browse Source

Implement FINI function for plugins

Serj Kalichev 11 years ago
parent
commit
98c3b2bc24

+ 9 - 4
clish/plugin.h

@@ -30,7 +30,12 @@ typedef struct clish_plugin_s clish_plugin_t;
 #define CLISH_PLUGIN_INIT_NAME "clish_plugin_init"
 #define CLISH_PLUGIN_INIT_FUNC(name) int name(void *clish_shell, clish_plugin_t *plugin)
 #define CLISH_PLUGIN_INIT CLISH_PLUGIN_INIT_FUNC(CLISH_PLUGIN_INIT_FNAME)
-#define CLISH_PLUGIN_FINI(name) int name(void *clish_shell, clish_plugin_t *plugin)
+
+/* Name of fini function within plugin */
+#define CLISH_PLUGIN_FINI_FNAME clish_plugin_fini
+#define CLISH_PLUGIN_FINI_NAME "clish_plugin_fini"
+#define CLISH_PLUGIN_FINI_FUNC(name) int name(void *clish_shell, clish_plugin_t *plugin)
+#define CLISH_PLUGIN_FINI CLISH_PLUGIN_FINI_FUNC(CLISH_PLUGIN_FINI_FNAME)
 
 #define CLISH_HOOK_INIT(name) int name(void *clish_context)
 #define CLISH_HOOK_FINI(name) int name(void *clish_context)
@@ -49,7 +54,7 @@ typedef struct clish_plugin_s clish_plugin_t;
 /* typedef void clish_shell_cmd_line_fn_t(clish_context_t *context, const char *cmd_line); */
 
 typedef CLISH_PLUGIN_INIT_FUNC(clish_plugin_init_t);
-typedef CLISH_PLUGIN_FINI(clish_plugin_fini_t);
+typedef CLISH_PLUGIN_FINI_FUNC(clish_plugin_fini_t);
 typedef CLISH_PLUGIN_SYM(clish_hook_action_fn_t);
 typedef CLISH_HOOK_INIT(clish_hook_init_fn_t);
 typedef CLISH_HOOK_FINI(clish_hook_fini_fn_t);
@@ -80,8 +85,8 @@ int clish_sym_clone(clish_sym_t *dst, clish_sym_t *src);
 /* Plugin */
 
 clish_plugin_t *clish_plugin_new(const char *name, const char *file);
-void clish_plugin_free(clish_plugin_t *instance);
-clish_plugin_init_t *clish_plugin_load(clish_plugin_t *instance);
+void clish_plugin_free(clish_plugin_t *instance, void *userdata);
+int clish_plugin_load(clish_plugin_t *instance, void *userdata);
 clish_sym_t *clish_plugin_get_sym(clish_plugin_t *instance,
 	const char *name, int type);
 clish_sym_t *clish_plugin_add_generic(clish_plugin_t *instance,

+ 27 - 10
clish/plugin/plugin.c

@@ -144,18 +144,25 @@ clish_plugin_t *clish_plugin_new(const char *name, const char *file)
 	this->dlhan = NULL;
 	/* Initialise the list of symbols */
 	this->syms = lub_list_new(clish_sym_compare);
+	/* Constructor and destructor */
+	this->init = NULL;
+	this->fini = NULL;
 
 	return this;
 }
 
 /*--------------------------------------------------------- */
-void clish_plugin_free(clish_plugin_t *this)
+void clish_plugin_free(clish_plugin_t *this, void *userdata)
 {
 	lub_list_node_t *iter;
 
 	if (!this)
 		return;
 
+	/* Execute destructor */
+	if (this->fini)
+		this->fini(userdata, this);
+
 	lub_string_free(this->file);
 	lub_string_free(this->name);
 
@@ -247,27 +254,37 @@ clish_sym_t *clish_plugin_get_sym(clish_plugin_t *this, const char *name, int ty
 }
 
 /*--------------------------------------------------------- */
-clish_plugin_init_t *clish_plugin_load(clish_plugin_t *this)
+int clish_plugin_load(clish_plugin_t *this, void *userdata)
 {
-	clish_plugin_init_t *plugin_init;
+	int res;
 
 	if (!this)
-		return NULL;
+		return -1;
 
+	/* Open dynamic library */
 	if (!(this->dlhan = dlopen(this->file, RTLD_NOW | RTLD_LOCAL))) {
 		fprintf(stderr, "Error: Can't open plugin %s: %s\n",
 			this->file, dlerror());
-		return NULL;
+		return -1;
 	}
-	plugin_init = (clish_plugin_init_t *)dlsym(this->dlhan, CLISH_PLUGIN_INIT_NAME);
-	if (!plugin_init) {
+
+	/* Get plugin init function */
+	this->init = (clish_plugin_init_t *)dlsym(this->dlhan, CLISH_PLUGIN_INIT_NAME);
+	if (!this->init) {
 		fprintf(stderr, "Error: Can't get plugin %s init function: %s\n",
 			this->file, dlerror());
-		dlclose(this->dlhan);
-		this->dlhan = NULL;
+		return -1;
 	}
 
-	return plugin_init;
+	/* Get plugin fini function */
+	this->fini = (clish_plugin_fini_t *)dlsym(this->dlhan, CLISH_PLUGIN_FINI_NAME);
+
+	/* Execute init function */
+	if ((res = this->init(userdata, this)))
+		fprintf(stderr, "Error: Plugin %s init retcode: %d\n",
+			this->file, res);
+
+	return res;
 }
 
 /*--------------------------------------------------------- */

+ 2 - 0
clish/plugin/private.h

@@ -22,4 +22,6 @@ struct clish_plugin_s {
 	char *name; /* Local plugin name. Can be used in builtin ref. */
 	lub_list_t *syms; /* List of plugin symbols */
 	void *dlhan; /* Handler of dlopen() */
+	clish_plugin_init_t *init; /* Init function (constructor) != NULL */
+	clish_plugin_fini_t *fini; /* Fini function (destructor) */
 };

+ 12 - 11
clish/shell/shell_new.c

@@ -118,7 +118,7 @@ static void clish_shell_init(clish_shell_t * this,
 }
 
 /*--------------------------------------------------------- */
-static void clish_shell_fini(clish_shell_t * this)
+static void clish_shell_fini(clish_shell_t *this)
 {
 	clish_view_t *view;
 	clish_ptype_t *ptype;
@@ -126,6 +126,17 @@ static void clish_shell_fini(clish_shell_t * this)
 	unsigned i;
 	lub_list_node_t *iter;
 
+	/* Free all loaded plugins */
+	while ((iter = lub_list__get_head(this->plugins))) {
+		/* Remove the symbol from the list */
+		lub_list_del(this->plugins, iter);
+		/* Free the instance */
+		clish_plugin_free((clish_plugin_t *)lub_list_node__get_data(iter),
+			(void *)this);
+		lub_list_node_free(iter);
+	}
+	lub_list_free(this->plugins);
+
 	/* delete each VIEW held  */
 	while ((view = lub_bintree_findfirst(&this->view_tree))) {
 		lub_bintree_remove(&this->view_tree, view);
@@ -144,16 +155,6 @@ static void clish_shell_fini(clish_shell_t * this)
 		clish_var_delete(var);
 	}
 
-	/* Free all loaded plugins */
-	while ((iter = lub_list__get_head(this->plugins))) {
-		/* Remove the symbol from the list */
-		lub_list_del(this->plugins, iter);
-		/* Free the instance */
-		clish_plugin_free((clish_plugin_t *)lub_list_node__get_data(iter));
-		lub_list_node_free(iter);
-	}
-	lub_list_free(this->plugins);
-
 	/* Free symbol list */
 	while ((iter = lub_list__get_head(this->syms))) {
 		/* Remove the symbol from the list */

+ 1 - 6
clish/shell/shell_plugin.c

@@ -22,7 +22,6 @@ int clish_shell_load_plugins(clish_shell_t *this)
 {
 	lub_list_node_t *iter;
 	clish_plugin_t *plugin;
-	clish_plugin_init_t *plugin_init;
 
 	assert(this);
 
@@ -30,12 +29,8 @@ int clish_shell_load_plugins(clish_shell_t *this)
 	for(iter = lub_list__get_head(this->plugins);
 		iter; iter = lub_list_node__get_next(iter)) {
 		plugin = (clish_plugin_t *)lub_list_node__get_data(iter);
-		if (!(plugin_init = clish_plugin_load(plugin)))
+		if (clish_plugin_load(plugin, (void *)this))
 			return -1;
-		plugin_init(this, plugin);
-		/* TODO: Check plugin_init() retval. If < 0 then
-		   destroy current plugin or exit on error.
-		*/
 #ifdef DEBUG
 		clish_plugin_dump(plugin);
 #endif

+ 10 - 0
examples/explugin/anplug.c

@@ -10,7 +10,17 @@ CLISH_PLUGIN_SYM(anplug_fn)
 
 CLISH_PLUGIN_INIT
 {
+	printf("anplug: INIT shell = %p\n", clish_shell);
 	clish_plugin_add_sym(plugin, anplug_fn, "an_fn");
+
+	return 0;
+}
+
+CLISH_PLUGIN_FINI
+{
+	printf("anplug: FINI this = %p\n", clish_shell);
+
+	return 0;
 }
 
 

+ 2 - 0
examples/explugin/explugin.c

@@ -11,6 +11,8 @@ CLISH_PLUGIN_SYM(explugin_fn)
 CLISH_PLUGIN_INIT
 {
 	clish_plugin_add_sym(plugin, explugin_fn, "hello");
+
+	return 0;
 }