anjuta-c-module.c 7.85 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
    anjuta-c-module.c
    Copyright (C) 2007 Sébastien Granjoux

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**
 * SECTION:anjuta-c-module
23
 * @title: AnjutaCModule
24
 * @short_description: Anjuta C module
25
 * @see_also: #AnjutaCPluginFactory
26 27
 * @include: libanjuta/anjuta-c-module.h
 * 
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
 * A module is the part of the plugin containing the code. For machine code
 * compiled from C sources by example, it is a shared library and contained in
 * a .so file on Linux. GLib provides a portable way to load dynamically such
 * code with #GModule objects.
 *
 * In GLib you can register a dynamic type which means that you links a GLib
 * type with a module. When the type is used for the first time the module is
 * loaded. When the type is not used anymore, the module is unloaded. Most of
 * the code necessary to do this is already written in GLib #GTypeModule object
 * except the load and unload function.
 *
 * #AnjutaCModule is used only by a #AnjutaCPluginFactory. It derives from
 * #GTypeModule and implements the load and unload function using a #GModule
 * object for a module written in C.
 *
 * Anjuta plugin types are not registered before loading the module.
 * The loading of the module is done explicitly and types are registered just 
 * after in a function included in the plugin. This function is named
 * anjuta_glue_register_components and has a #GTypeModule as argument.
 * The plugin must registers at the least the plugin type dynamically. It can
 * register other types, but this is currently not used.
 *
 * After loading a module one or more plugin objects will be created using the
 * name of the plugin type which has just been registered. The module
 * will stay loaded while at least one plugin object is present. If all
 * plugins objects are destroyed the unload function will be called and the
 * module can be unloaded and removed from memory.
 *
 * It could be useful that some modules stay in memory even if there is no
 * object using it. A typical example is if some plugin code or some code of
 * a library used by a plugin registers a GLib type statically. GLib types can
 * be registered statically at run time but cannot be unregistered later.
 * The code (or rather the data used in the registration) must stay in the 
 * memory even if the type is not used. In order to avoid this, you must
 * register every type dynamically. You could have other situations where a
 * module cannot be unloaded. By default, Anjuta plugin modules are not
 * unloaded unless it is explicitly allowed.
65 66 67 68 69 70
 */

#include "config.h"

#include "anjuta-c-module.h"

71 72
#include <libanjuta/interfaces/ianjuta-plugin-factory.h>

73 74
#include <gmodule.h>

75 76
#define ANJUTA_PLUGIN_REGISTRATION	"anjuta_glue_register_components"	

77 78 79 80 81 82 83 84 85 86 87 88 89 90
/* Types
 *---------------------------------------------------------------------------*/

struct _AnjutaCModuleClass
{
	GTypeModuleClass parent;
};

struct _AnjutaCModule
{
	GTypeModule parent;

	GModule *library;
	gchar *full_name;
91
	IAnjutaPluginFactoryError error;
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
};

typedef void (*AnjutaRegisterFunc) (GTypeModule *);

G_DEFINE_TYPE (AnjutaCModule, anjuta_c_module, G_TYPE_TYPE_MODULE)

/* Private functions
 *---------------------------------------------------------------------------*/

/* GTypeModule functions
 *---------------------------------------------------------------------------*/	

static gboolean
anjuta_c_module_load (GTypeModule *gmodule)
{
	AnjutaCModule *module = ANJUTA_C_MODULE (gmodule);
	AnjutaRegisterFunc func;

	g_return_val_if_fail (module->full_name != NULL, FALSE);

	/* Load the module and register the plugins */
	module->library = g_module_open (module->full_name, 0);

	if (module->library == NULL)
	{
117 118 119 120 121 122 123 124
		if (!g_file_test (module->full_name, G_FILE_TEST_IS_REGULAR))
		{
			module->error = IANJUTA_PLUGIN_FACTORY_MISSING_MODULE;
		}
		else
		{
			module->error = IANJUTA_PLUGIN_FACTORY_INVALID_MODULE;
		}
125 126 127
		return FALSE;
	}

128
	if (!g_module_symbol (module->library, ANJUTA_PLUGIN_REGISTRATION, (gpointer *)(gpointer)&func))
129
    {
130
		module->error = IANJUTA_PLUGIN_FACTORY_MISSING_FUNCTION;
131 132 133 134 135 136 137
		g_module_close (module->library);

		return FALSE;
	}
  
	/* Register all types */
	(* func) (gmodule);
138
	module->error = IANJUTA_PLUGIN_FACTORY_OK;
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184

	return TRUE;
}

static void
anjuta_c_module_unload (GTypeModule *gmodule)
{
	AnjutaCModule *module = ANJUTA_C_MODULE (gmodule);

	g_module_close (module->library);
}

/* GObject functions
 *---------------------------------------------------------------------------*/

/* finalize is the last destruction step. It must free all memory allocated
 * with instance_init. It is called only one time just before releasing all
 * memory */

static void
anjuta_c_module_finalize (GObject *object)
{
	AnjutaCModule* module = ANJUTA_C_MODULE (object);

	g_free (module->full_name);
	
	G_OBJECT_CLASS (anjuta_c_module_parent_class)->finalize (object);
}


static void
anjuta_c_module_class_init (AnjutaCModuleClass *klass)
{
	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
	GTypeModuleClass *gmodule_class = (GTypeModuleClass *)klass;

	gobject_class->finalize = anjuta_c_module_finalize;

	gmodule_class->load = anjuta_c_module_load;
	gmodule_class->unload = anjuta_c_module_unload;
}

static void
anjuta_c_module_init (AnjutaCModule *module)
{
	module->full_name = NULL;
185 186 187 188 189 190
	module->error = IANJUTA_PLUGIN_FACTORY_OK;
}

/* Public functions
 *---------------------------------------------------------------------------*/

191 192 193 194 195 196 197 198 199
/**
 * anjuta_c_module_get_last_error:
 * @module: AnjutaCModule object
 * @err: return location for a GError
 *
 * Receives the error that occured when the module was loaded
 *
 * Returns: TRUE if there was an Error, FALSE otherwise
 */
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
gboolean
anjuta_c_module_get_last_error (AnjutaCModule *module, GError** err)
{
	g_return_val_if_fail (module->full_name != NULL, FALSE);

	switch (module->error)
	{
	case IANJUTA_PLUGIN_FACTORY_OK:
			return FALSE;
	case IANJUTA_PLUGIN_FACTORY_MISSING_MODULE:
			g_set_error (err, IANJUTA_PLUGIN_FACTORY_ERROR,
					 	module->error,
					 	_("Unable to find plugin module %s"), module->full_name);
			return TRUE;
	case IANJUTA_PLUGIN_FACTORY_INVALID_MODULE:
			g_set_error (err, IANJUTA_PLUGIN_FACTORY_ERROR,
216 217
					 	 module->error,
						 "%s", g_module_error());
218 219 220 221 222 223 224 225 226 227 228 229 230
			return TRUE;
	case IANJUTA_PLUGIN_FACTORY_MISSING_FUNCTION:
			g_set_error (err, IANJUTA_PLUGIN_FACTORY_ERROR,
						module->error,
						_("Unable to find plugin registration function %s in module %s"),
					 	ANJUTA_PLUGIN_REGISTRATION, module->full_name);
			return TRUE;
	default:
			g_set_error (err, IANJUTA_PLUGIN_FACTORY_ERROR,
						module->error,
						_("Unknown error in module %s"), module->full_name);
			return TRUE;
	}		
231 232 233 234 235
}

/* Creation and Destruction
 *---------------------------------------------------------------------------*/

236 237 238 239 240 241 242 243 244
/**
 * anjuta_c_module_new:
 * @path: The full path of the module
 * @name: The name of the module
 *
 * Create a new #AnjutaCModule object.
 *
 * Return value: a new #AnjutaCModule object.
 */
245 246 247 248 249 250 251 252 253 254 255
AnjutaCModule*
anjuta_c_module_new (const gchar *path, const char *name)
{
	AnjutaCModule *module;

	module = g_object_new (ANJUTA_TYPE_C_MODULE, NULL);
	module->full_name = g_module_build_path (path, name);
	g_type_module_set_name (G_TYPE_MODULE (module), module->full_name);
		
	return module;
}