3 * A Nautilus extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
9 * This Program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This Program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this Library; see the file COPYING. If not,
21 * write to the Free Software Foundation, Inc., 59 Temple Place,
22 * Suite 330, Boston, MA 02111-1307, USA.
25 * Frederic Ruaudel <grumz@grumz.net>
26 * Rodrigo Moya <rodrigo@gnome-db.org>
27 * Pierre Wieser <pwieser@trychlos.org>
28 * ... and many others (see AUTHORS)
35 /* this is a module to test how to use the GLib dynamic-loading functions
36 * it tries to load, then unload, a test-module-plugin.so plugin
38 * more specifically, I am interested on releasing allocated resources
43 #include <glib-object.h>
46 #define PLUGIN_NAME "test_module_plugin"
50 /* this is first version
52 static GModule
*load_plugin( void );
53 static void call_plugin_fn( GModule
*module
);
54 static void unload_plugin( GModule
*module
);
57 main( int argc
, char **argv
)
63 /* dynamically load the module */
64 module
= load_plugin();
67 /* call a function in the module */
68 call_plugin_fn( module
);
70 /* unload the module */
71 unload_plugin( module
);
85 if( g_module_supported()){
87 module_path
= g_module_build_path( PKGLIBDIR
, PLUGIN_NAME
);
88 module
= g_module_open( module_path
, G_MODULE_BIND_LAZY
| G_MODULE_BIND_LOCAL
);
90 g_printerr( "%s: %s\n", module_path
, g_module_error());
92 g_free( module_path
);
99 call_plugin_fn( GModule
*module
)
101 typedef void ( *PluginFn
)( GModule
*module
);
104 if( !g_module_symbol( module
, "say_hello", ( gpointer
* ) &plugin_fn
)){
105 g_printerr( "%s\n", g_module_error());
109 g_printerr( "%s\n", g_module_error());
116 unload_plugin( GModule
*module
)
118 if( !g_module_close( module
)){
119 g_printerr( "%s\n", g_module_error());
125 * Having the plugin register dynamic GTypes require a GTypeModule
126 * This GTtypeModule is provided by the program as a GTypeModule-derived object
127 * NAModule embeds the GModule
131 * - the main program (the loader) should define a GTypeModule derived class
133 * - the GTypeModule derived class (here NAModule) embeds a GModule pointer
135 * - when loading plugins:
137 * > allocate a new GTypeModule derived object for each module
138 * setup the path here
140 * > g_type_module_use() it
141 * this triggers the on_load() virtual method on GTypeModule derived class
142 * in on_load_derived(), g_module_open() the plugin and check the API
144 * on_load_derived() may return FALSE
145 * while dynamic types have not been registered, we are always safe to unref
146 * the allocated GTypeModule derived object
147 * setup the GModule pointer on the loaded library
149 * so, if g_module_use() returns FALSE, just unref the object
151 * so, g_module_use() cannot be called from instance_init or
152 * instance_constructed (which have no return value)
154 * At the end, it is impossible to release the GTypeModule objects.
155 * But we can safely unuse their loaded libraries.
157 * The main program does not known which GType or GInterface the plugin
159 * Nautilus defines a get_types() API, and then allocates an object for each
160 * returned type. It is then easy to check if the object implements a given
162 * Nautilus never release these objects.
163 * We may also ask the plugin to just allocate itself its own management object,
164 * returning it to the program (returning a pointer is possible because we are
165 * in the same process).
168 #define NA_MODULE_TYPE ( na_module_get_type())
169 #define NA_MODULE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_MODULE_TYPE, NAModule ))
170 #define NA_MODULE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_MODULE_TYPE, NAModuleClass ))
171 #define NA_IS_MODULE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_MODULE_TYPE ))
172 #define NA_IS_MODULE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_MODULE_TYPE ))
173 #define NA_MODULE_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_MODULE_TYPE, NAModuleClass ))
175 typedef struct _NAModulePrivate NAModulePrivate
;
176 typedef struct _NAModuleClassPrivate NAModuleClassPrivate
;
181 NAModulePrivate
*private;
187 GTypeModuleClass parent
;
188 NAModuleClassPrivate
*private;
192 GType
na_module_get_type ( void );
194 /* private class data
196 struct _NAModuleClassPrivate
{
197 void *empty
; /* so that gcc -pedantic is happy */
200 /* private instance data
202 struct _NAModulePrivate
{
203 gboolean dispose_has_run
;
207 static GTypeModuleClass
*st_parent_class
= NULL
;
209 static GType
register_type( void );
210 static void class_init( NAModuleClass
*klass
);
211 static void instance_init( GTypeInstance
*instance
, gpointer klass
);
212 static void instance_dispose( GObject
*object
);
213 static void instance_finalize( GObject
*object
);
215 static NAModule
*load_plugin( void );
216 static gboolean
on_module_load( GTypeModule
*module
);
217 static void call_plugin_fn( NAModule
*module
);
218 static void on_unload_plugin( GTypeModule
*module
);
221 na_module_get_type( void )
223 static GType object_type
= 0;
226 object_type
= register_type();
229 return( object_type
);
233 register_type( void )
235 static const gchar
*thisfn
= "na_module_register_type";
238 static GTypeInfo info
= {
239 sizeof( NAModuleClass
),
240 ( GBaseInitFunc
) NULL
,
241 ( GBaseFinalizeFunc
) NULL
,
242 ( GClassInitFunc
) class_init
,
247 ( GInstanceInitFunc
) instance_init
250 g_debug( "%s", thisfn
);
252 type
= g_type_register_static( G_TYPE_TYPE_MODULE
, "NAModule", &info
, 0 );
258 class_init( NAModuleClass
*klass
)
260 static const gchar
*thisfn
= "na_module_class_init";
261 GObjectClass
*object_class
;
262 GTypeModuleClass
*module_class
;
264 g_debug( "%s: klass=%p", thisfn
, ( void * ) klass
);
266 st_parent_class
= g_type_class_peek_parent( klass
);
268 object_class
= G_OBJECT_CLASS( klass
);
269 object_class
->dispose
= instance_dispose
;
270 object_class
->finalize
= instance_finalize
;
272 module_class
= G_TYPE_MODULE_CLASS( klass
);
273 module_class
->load
= on_module_load
;
274 module_class
->unload
= on_unload_plugin
;
276 klass
->private = g_new0( NAModuleClassPrivate
, 1 );
280 instance_init( GTypeInstance
*instance
, gpointer klass
)
282 static const gchar
*thisfn
= "na_module_instance_init";
285 g_return_if_fail( NA_IS_MODULE( instance
));
287 g_debug( "%s: instance=%p (%s), klass=%p",
288 thisfn
, ( void * ) instance
, G_OBJECT_TYPE_NAME( instance
), ( void * ) klass
);
290 self
= NA_MODULE( instance
);
292 self
->private = g_new0( NAModulePrivate
, 1 );
294 self
->private->dispose_has_run
= FALSE
;
298 instance_dispose( GObject
*object
)
300 static const gchar
*thisfn
= "na_module_instance_dispose";
303 g_return_if_fail( NA_IS_MODULE( object
));
305 self
= NA_MODULE( object
);
307 if( !self
->private->dispose_has_run
){
309 g_debug( "%s: object=%p (%s)", thisfn
, ( void * ) object
, G_OBJECT_TYPE_NAME( object
));
311 self
->private->dispose_has_run
= TRUE
;
313 /* should trigger unload of the plugin */
315 * GLib-GObject-WARNING **: gtypemodule.c:111: unsolicitated invocation of g_object_dispose() on GTypeModule
317 /*g_type_module_unuse( G_TYPE_MODULE( self ));*/
319 if( G_OBJECT_CLASS( st_parent_class
)->dispose
){
320 G_OBJECT_CLASS( st_parent_class
)->dispose( object
);
326 instance_finalize( GObject
*object
)
328 static const gchar
*thisfn
= "na_module_instance_finalize";
331 g_return_if_fail( NA_IS_MODULE( object
));
333 g_debug( "%s: object=%p (%s)", thisfn
, ( void * ) object
, G_OBJECT_TYPE_NAME( object
));
335 self
= NA_MODULE( object
);
337 g_free( self
->private );
339 /* chain call to parent class */
340 if( G_OBJECT_CLASS( st_parent_class
)->finalize
){
341 G_OBJECT_CLASS( st_parent_class
)->finalize( object
);
346 main( int argc
, char **argv
)
352 /* dynamically load the module */
353 module
= load_plugin();
356 /* call a function in the module */
357 call_plugin_fn( module
);
359 /* try to just unref the NAModule */
361 /*g_object_unref( module );*/
363 /* try to unload the plugin */
364 g_type_module_unuse( G_TYPE_MODULE( module
));
365 /* then unref the object */
367 * it happens that releasing the GTypeModule after having registered a GType or a
368 * GInterface is impossible
369 * see http://git.gnome.org/browse/glib/tree/gobject/gtypemodule.c
370 * and http://library.gnome.org/devel/gobject/unstable/GTypeModule.html#g-type-module-unuse
372 /*g_object_unref( module );*/
385 if( g_module_supported()){
387 module
= g_object_new( NA_MODULE_TYPE
, NULL
);
388 g_debug( "test_module_load_plugin: module=%p", ( void * ) module
);
390 if( !g_type_module_use( G_TYPE_MODULE( module
))){
391 g_object_unref( module
);
399 on_module_load( GTypeModule
*module
)
403 NAModule
*na_module
= NA_MODULE( module
);
405 g_debug( "test_module_on_module_load" );
408 module_path
= g_module_build_path( PKGLIBDIR
, PLUGIN_NAME
);
410 g_debug( "test_module_on_module_load: opening the library" );
411 na_module
->private->plugin
= g_module_open( module_path
, G_MODULE_BIND_LAZY
| G_MODULE_BIND_LOCAL
);
413 if( !na_module
->private->plugin
){
414 g_printerr( "%s: %s\n", module_path
, g_module_error());
418 g_free( module_path
);
424 call_plugin_fn( NAModule
*module
)
426 typedef void ( *PluginInit
)( NAModule
*module
);
427 PluginInit plugin_fn
;
429 if( !g_module_symbol( module
->private->plugin
, "plugin_init", ( gpointer
* ) &plugin_fn
)){
430 g_printerr( "%s\n", g_module_error());
434 g_printerr( "%s\n", g_module_error());
441 on_unload_plugin( GTypeModule
*module
)
443 g_debug( "test_module_on_unload_plugin" );
444 if( !g_module_close( NA_MODULE( module
)->private->plugin
)){
445 g_printerr( "%s\n", g_module_error());