diff options
-rw-r--r-- | libpeas/peas-engine.c | 33 | ||||
-rw-r--r-- | libpeas/peas-extension-set.c | 18 | ||||
-rw-r--r-- | libpeas/peas-extension.c | 32 | ||||
-rw-r--r-- | libpeas/peas-introspection.c | 29 | ||||
-rw-r--r-- | libpeas/peas-introspection.h | 4 | ||||
-rw-r--r-- | libpeas/peas-object-module.c | 116 | ||||
-rw-r--r-- | libpeas/peas-object-module.h | 10 | ||||
-rw-r--r-- | libpeas/peas-utils.c | 40 | ||||
-rw-r--r-- | libpeas/peas-utils.h | 2 | ||||
-rw-r--r-- | tests/libpeas/introspection/Makefile.am | 2 | ||||
-rw-r--r-- | tests/libpeas/introspection/introspection-abstract.c | 132 | ||||
-rw-r--r-- | tests/libpeas/introspection/introspection-abstract.h | 60 | ||||
-rw-r--r-- | tests/libpeas/plugins/extension-c/Makefile.am | 4 | ||||
-rw-r--r-- | tests/libpeas/plugins/extension-c/extension-c-abstract.c | 55 | ||||
-rw-r--r-- | tests/libpeas/plugins/extension-c/extension-c-abstract.h | 52 | ||||
-rw-r--r-- | tests/libpeas/plugins/extension-c/extension-c-plugin.c | 7 | ||||
-rw-r--r-- | tests/libpeas/plugins/extension-lua/extension-lua51.lua | 6 | ||||
-rw-r--r-- | tests/libpeas/plugins/extension-python/extension-py.py.in | 6 | ||||
-rw-r--r-- | tests/libpeas/testing/testing-extension.c | 51 |
19 files changed, 548 insertions, 111 deletions
diff --git a/libpeas/peas-engine.c b/libpeas/peas-engine.c index 3b35145..5713cb0 100644 --- a/libpeas/peas-engine.c +++ b/libpeas/peas-engine.c @@ -57,6 +57,9 @@ * plugins and their extensions from within your application.</para> * </listitem> * </itemizedlist> + * + * Since libpeas 1.22, @extension_type can be an Abstract #GType + * and not just an Interface #GType. **/ /* Signals */ @@ -1274,6 +1277,9 @@ peas_engine_unload_plugin (PeasEngine *engine, * Returns if @info provides an extension for @extension_type. * If the @info is not loaded than %FALSE will always be returned. * + * Since libpeas 1.22, @extension_type can be an Abstract #GType + * and not just an Interface #GType. + * * Returns: if @info provides an extension for @extension_type. */ gboolean @@ -1285,7 +1291,8 @@ peas_engine_provides_extension (PeasEngine *engine, g_return_val_if_fail (PEAS_IS_ENGINE (engine), FALSE); g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (G_TYPE_IS_INTERFACE (extension_type), FALSE); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (extension_type) || + G_TYPE_IS_ABSTRACT (extension_type), FALSE); if (!peas_plugin_info_is_loaded (info)) return FALSE; @@ -1303,10 +1310,13 @@ peas_engine_provides_extension (PeasEngine *engine, * @parameters: (allow-none) (array length=n_parameters): * an array of #GParameter. * - * If the plugin identified by @info implements the @extension_type interface, + * If the plugin identified by @info implements the @extension_type, * then this function will return a new instance of this implementation, * wrapped in a new #PeasExtension instance. Otherwise, it will return %NULL. * + * Since libpeas 1.22, @extension_type can be an Abstract #GType + * and not just an Interface #GType. + * * See peas_engine_create_extension() for more information. * * Returns: (transfer full): a new instance of #PeasExtension wrapping @@ -1324,8 +1334,9 @@ peas_engine_create_extensionv (PeasEngine *engine, g_return_val_if_fail (PEAS_IS_ENGINE (engine), NULL); g_return_val_if_fail (info != NULL, NULL); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (extension_type) || + G_TYPE_IS_ABSTRACT (extension_type), NULL); g_return_val_if_fail (peas_plugin_info_is_loaded (info), NULL); - g_return_val_if_fail (G_TYPE_IS_INTERFACE (extension_type), FALSE); loader = get_plugin_loader (engine, info->loader_id); extension = peas_plugin_loader_create_extension (loader, info, extension_type, @@ -1351,10 +1362,13 @@ peas_engine_create_extensionv (PeasEngine *engine, * @var_args: the value of the first property, followed optionally by more * name/value pairs, followed by %NULL. * - * If the plugin identified by @info implements the @extension_type interface, + * If the plugin identified by @info implements the @extension_type, * then this function will return a new instance of this implementation, * wrapped in a new #PeasExtension instance. Otherwise, it will return %NULL. * + * Since libpeas 1.22, @extension_type can be an Abstract #GType + * and not just an Interface #GType. + * * See peas_engine_create_extension() for more information. * * Returns: a new instance of #PeasExtension wrapping @@ -1374,7 +1388,8 @@ peas_engine_create_extension_valist (PeasEngine *engine, g_return_val_if_fail (PEAS_IS_ENGINE (engine), NULL); g_return_val_if_fail (info != NULL, NULL); g_return_val_if_fail (peas_plugin_info_is_loaded (info), NULL); - g_return_val_if_fail (G_TYPE_IS_INTERFACE (extension_type), FALSE); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (extension_type) || + G_TYPE_IS_ABSTRACT (extension_type), FALSE); if (!peas_utils_valist_to_parameter_list (extension_type, first_property, var_args, ¶meters, @@ -1403,7 +1418,7 @@ peas_engine_create_extension_valist (PeasEngine *engine, * @...: the value of the first property, followed optionally by more * name/value pairs, followed by %NULL. * - * If the plugin identified by @info implements the @extension_type interface, + * If the plugin identified by @info implements the @extension_type, * then this function will return a new instance of this implementation, * wrapped in a new #PeasExtension instance. Otherwise, it will return %NULL. * @@ -1416,6 +1431,9 @@ peas_engine_create_extension_valist (PeasEngine *engine, * principle of never giving you the actual object (also because it might as * well *not* be an actual object). * + * Since libpeas 1.22, @extension_type can be an Abstract #GType + * and not just an Interface #GType. + * * Returns: a new instance of #PeasExtension wrapping * the @extension_type instance, or %NULL. */ @@ -1432,7 +1450,8 @@ peas_engine_create_extension (PeasEngine *engine, g_return_val_if_fail (PEAS_IS_ENGINE (engine), NULL); g_return_val_if_fail (info != NULL, NULL); g_return_val_if_fail (peas_plugin_info_is_loaded (info), NULL); - g_return_val_if_fail (G_TYPE_IS_INTERFACE (extension_type), FALSE); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (extension_type) || + G_TYPE_IS_ABSTRACT (extension_type), FALSE); va_start (var_args, first_property); exten = peas_engine_create_extension_valist (engine, info, extension_type, diff --git a/libpeas/peas-extension-set.c b/libpeas/peas-extension-set.c index cb3f9cc..a4e0f3f 100644 --- a/libpeas/peas-extension-set.c +++ b/libpeas/peas-extension-set.c @@ -615,6 +615,9 @@ peas_extension_set_foreach (PeasExtensionSet *set, * * If @engine is %NULL, then the default engine will be used. * + * Since libpeas 1.22, @exten_type can be an Abstract #GType + * and not just an Interface #GType. + * * See peas_extension_set_new() for more information. * * Returns: (transfer full): a new instance of #PeasExtensionSet. @@ -628,7 +631,8 @@ peas_extension_set_newv (PeasEngine *engine, PeasParameterArray construct_properties = { n_parameters, parameters }; g_return_val_if_fail (engine == NULL || PEAS_IS_ENGINE (engine), NULL); - g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type), NULL); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type) || + G_TYPE_IS_ABSTRACT (exten_type), NULL); return PEAS_EXTENSION_SET (g_object_new (PEAS_TYPE_EXTENSION_SET, "engine", engine, @@ -649,6 +653,9 @@ peas_extension_set_newv (PeasEngine *engine, * * If @engine is %NULL, then the default engine will be used. * + * Since libpeas 1.22, @exten_type can be an Abstract #GType + * and not just an Interface #GType. + * * See peas_extension_set_new() for more information. * * Returns: a new instance of #PeasExtensionSet. @@ -664,7 +671,8 @@ peas_extension_set_new_valist (PeasEngine *engine, PeasExtensionSet *set; g_return_val_if_fail (engine == NULL || PEAS_IS_ENGINE (engine), NULL); - g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type), NULL); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type) || + G_TYPE_IS_ABSTRACT (exten_type), NULL); if (!peas_utils_valist_to_parameter_list (exten_type, first_property, var_args, ¶meters, @@ -702,6 +710,9 @@ peas_extension_set_new_valist (PeasEngine *engine, * * If @engine is %NULL, then the default engine will be used. * + * Since libpeas 1.22, @exten_type can be an Abstract #GType + * and not just an Interface #GType. + * * See peas_engine_create_extension() for more information. * * Returns: a new instance of #PeasExtensionSet. @@ -716,7 +727,8 @@ peas_extension_set_new (PeasEngine *engine, PeasExtensionSet *set; g_return_val_if_fail (engine == NULL || PEAS_IS_ENGINE (engine), NULL); - g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type), NULL); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type) || + G_TYPE_IS_ABSTRACT (exten_type), NULL); va_start (var_args, first_property); set = peas_extension_set_new_valist (engine, exten_type, first_property, var_args); diff --git a/libpeas/peas-extension.c b/libpeas/peas-extension.c index 773d9f2..8e46920 100644 --- a/libpeas/peas-extension.c +++ b/libpeas/peas-extension.c @@ -37,8 +37,8 @@ * loaded plugins. * * To properly use the proxy instances, you will need GObject-introspection - * data for the #GInterface or #GObjectClass you want to use as an extension - * point. For instance, if you wish to use #PeasActivatable, you will need to + * data for the #GType you want to use as an extension point. + * For instance, if you wish to use #PeasActivatable, you will need to * put the following code excerpt in the engine initialization code, in order * to load the required "Peas" typelib: * @@ -47,7 +47,7 @@ * "Peas", "1.0", 0, NULL); * ]| * - * You should proceed the same way for any namespace which provides interfaces + * You should proceed the same way for any namespace which provides types * you want to use as extension points. GObject-introspection data is required * for all the supported languages, even for C. * @@ -72,7 +72,7 @@ G_DEFINE_QUARK (peas-extension-type, extension_type) static GICallableInfo * get_method_info (PeasExtension *exten, const gchar *method_name, - GType *interface) + GType *gtype) { guint i; GType exten_type; @@ -85,8 +85,8 @@ get_method_info (PeasExtension *exten, if (method_info != NULL) { - if (interface != NULL) - *interface = exten_type; + if (gtype != NULL) + *gtype = exten_type; return method_info; } @@ -99,15 +99,15 @@ get_method_info (PeasExtension *exten, if (method_info != NULL) { - if (interface != NULL) - *interface = interfaces[i]; + if (gtype != NULL) + *gtype = interfaces[i]; break; } } if (method_info == NULL) - g_warning ("Could not find the interface for method '%s'", method_name); + g_warning ("Could not find the GType for method '%s'", method_name); g_free (interfaces); return method_info; @@ -117,7 +117,7 @@ get_method_info (PeasExtension *exten, * peas_extension_get_extension_type: * @exten: A #PeasExtension. * - * Get the type of the extension interface of the object proxied by @exten. + * Get the #GType of the extension proxied by @exten. * * Return value: The #GType proxied by @exten. * @@ -154,7 +154,7 @@ peas_extension_get_extension_type (PeasExtension *exten) * * Return value: %TRUE on successful call. * - * Deprecated: 1.2: Use the interface directly instead. + * Deprecated: 1.2: Use the object directly instead. */ gboolean peas_extension_call (PeasExtension *exten, @@ -186,7 +186,7 @@ peas_extension_call (PeasExtension *exten, * * Return value: %TRUE on successful call. * - * Deprecated: 1.2: Use the interface directly instead. + * Deprecated: 1.2: Use the object directly instead. */ gboolean peas_extension_call_valist (PeasExtension *exten, @@ -241,7 +241,7 @@ peas_extension_call_valist (PeasExtension *exten, * * Return value: %TRUE on successful call. * - * Deprecated: 1.2: Use the interface directly instead. + * Deprecated: 1.2: Use the object directly instead. */ gboolean peas_extension_callv (PeasExtension *exten, @@ -250,19 +250,19 @@ peas_extension_callv (PeasExtension *exten, GIArgument *return_value) { GICallableInfo *method_info; - GType interface; + GType gtype; gboolean success; g_return_val_if_fail (PEAS_IS_EXTENSION (exten), FALSE); g_return_val_if_fail (method_name != NULL, FALSE); - method_info = get_method_info (exten, method_name, &interface); + method_info = get_method_info (exten, method_name, >ype); /* Already warned */ if (method_info == NULL) return FALSE; - success = peas_gi_method_call (G_OBJECT (exten), method_info, interface, + success = peas_gi_method_call (G_OBJECT (exten), method_info, gtype, method_name, args, return_value); g_base_info_unref (method_info); diff --git a/libpeas/peas-introspection.c b/libpeas/peas-introspection.c index 89aa41e..49ac178 100644 --- a/libpeas/peas-introspection.c +++ b/libpeas/peas-introspection.c @@ -239,44 +239,44 @@ peas_gi_argument_to_pointer (GITypeInfo *type_info, } GICallableInfo * -peas_gi_get_method_info (GType iface_type, +peas_gi_get_method_info (GType gtype, const gchar *method_name) { GIRepository *repo; - GIBaseInfo *iface_info; + GIBaseInfo *type_info; GIFunctionInfo *func_info; repo = g_irepository_get_default (); - iface_info = g_irepository_find_by_gtype (repo, iface_type); - if (iface_info == NULL) + type_info = g_irepository_find_by_gtype (repo, gtype); + if (type_info == NULL) { g_warning ("Type not found in introspection: '%s'", - g_type_name (iface_type)); + g_type_name (gtype)); return NULL; } - switch (g_base_info_get_type (iface_info)) + switch (g_base_info_get_type (type_info)) { case GI_INFO_TYPE_OBJECT: - func_info = g_object_info_find_method ((GIObjectInfo *) iface_info, + func_info = g_object_info_find_method ((GIObjectInfo *) type_info, method_name); break; case GI_INFO_TYPE_INTERFACE: - func_info = g_interface_info_find_method ((GIInterfaceInfo *) iface_info, + func_info = g_interface_info_find_method ((GIInterfaceInfo *) type_info, method_name); break; default: func_info = NULL; } - g_base_info_unref (iface_info); + g_base_info_unref (type_info); return (GICallableInfo *) func_info; } gboolean peas_gi_method_call (GObject *instance, GICallableInfo *func_info, - GType iface_type, + GType gtype, const gchar *method_name, GIArgument *args, GIArgument *return_value) @@ -289,8 +289,9 @@ peas_gi_method_call (GObject *instance, g_return_val_if_fail (G_IS_OBJECT (instance), FALSE); g_return_val_if_fail (func_info != NULL, FALSE); - g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface_type), FALSE); - g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (instance, iface_type), + g_return_val_if_fail (G_TYPE_IS_INTERFACE (gtype) || + G_TYPE_IS_ABSTRACT (gtype), FALSE); + g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (instance, gtype), FALSE); g_return_val_if_fail (method_name != NULL, FALSE); @@ -311,14 +312,14 @@ peas_gi_method_call (GObject *instance, n_in_args++; g_debug ("Calling '%s.%s' on '%p'", - g_type_name (iface_type), method_name, instance); + g_type_name (gtype), method_name, instance); ret = g_function_info_invoke (func_info, in_args, n_in_args, out_args, n_out_args, return_value, &error); if (!ret) { g_warning ("Error while calling '%s.%s': %s", - g_type_name (iface_type), method_name, error->message); + g_type_name (gtype), method_name, error->message); g_error_free (error); } diff --git a/libpeas/peas-introspection.h b/libpeas/peas-introspection.h index 53af722..e5f3bbd 100644 --- a/libpeas/peas-introspection.h +++ b/libpeas/peas-introspection.h @@ -27,7 +27,7 @@ G_BEGIN_DECLS -GICallableInfo *peas_gi_get_method_info (GType iface_type, +GICallableInfo *peas_gi_get_method_info (GType gtype, const gchar *method_name); void peas_gi_valist_to_arguments (GICallableInfo *callable_info, @@ -39,7 +39,7 @@ void peas_gi_argument_to_pointer (GITypeInfo *type_info, gpointer ptr); gboolean peas_gi_method_call (GObject *instance, GICallableInfo *method_info, - GType iface_type, + GType gtype, const gchar *method_name, GIArgument *args, GIArgument *return_value); diff --git a/libpeas/peas-object-module.c b/libpeas/peas-object-module.c index fbd81f2..6711667 100644 --- a/libpeas/peas-object-module.c +++ b/libpeas/peas-object-module.c @@ -40,6 +40,9 @@ * of extensions. It will be used by C extensions implementors to register * extension implementations from within the peas_register_types module * function. + * + * Since libpeas 1.22, @extension_type can be an Abstract #GType + * and not just an Interface #GType. **/ typedef void (*PeasObjectModuleRegisterFunc) (PeasObjectModule *module); @@ -57,11 +60,11 @@ enum { static GParamSpec *properties[N_PROPERTIES] = { NULL }; typedef struct { - GType iface_type; + GType exten_type; PeasFactoryFunc func; gpointer user_data; GDestroyNotify destroy_func; -} InterfaceImplementation; +} ExtensionImplementation; struct _PeasObjectModulePrivate { GModule *library; @@ -171,7 +174,7 @@ peas_object_module_unload (GTypeModule *gmodule) { PeasObjectModule *module = PEAS_OBJECT_MODULE (gmodule); PeasObjectModulePrivate *priv = GET_PRIV (module); - InterfaceImplementation *impls; + ExtensionImplementation *impls; guint i; g_module_close (priv->library); @@ -179,7 +182,7 @@ peas_object_module_unload (GTypeModule *gmodule) priv->library = NULL; priv->register_func = NULL; - impls = (InterfaceImplementation *) priv->implementations->data; + impls = (ExtensionImplementation *) priv->implementations->data; for (i = 0; i < priv->implementations->len; ++i) { if (impls[i].destroy_func != NULL) @@ -196,7 +199,7 @@ peas_object_module_init (PeasObjectModule *module) PeasObjectModulePrivate *priv = GET_PRIV (module); priv->implementations = g_array_new (FALSE, FALSE, - sizeof (InterfaceImplementation)); + sizeof (ExtensionImplementation)); } static void @@ -433,36 +436,38 @@ peas_object_module_new_embedded (const gchar *module_name, /** * peas_object_module_create_object: (skip) * @module: A #PeasObjectModule. - * @interface: The #GType of the extension interface. + * @exten_type: The #GType of the extension. * @n_parameters: The number of paramteters. * @parameters: (array length=n_parameters): The parameters. * - * Creates an object for the @interface passing @n_parameters + * Creates an object for the @exten_type passing @n_parameters * and @parameters to the #PeasFactoryFunc. If @module does - * not provide a #PeasFactoryFunc for @interface then + * not provide a #PeasFactoryFunc for @exten_type then * %NULL is returned. * + * Since libpeas 1.22, @exten_type can be an Abstract #GType + * and not just an Interface #GType. + * * Return value: (transfer full): The created object, or %NULL. */ GObject * peas_object_module_create_object (PeasObjectModule *module, - GType interface, + GType exten_type, guint n_parameters, GParameter *parameters) { PeasObjectModulePrivate *priv = GET_PRIV (module); guint i; - InterfaceImplementation *impls; + ExtensionImplementation *impls; g_return_val_if_fail (PEAS_IS_OBJECT_MODULE (module), NULL); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type) || + G_TYPE_IS_ABSTRACT (exten_type), NULL); - if (interface != PEAS_TYPE_PLUGIN_LOADER) - g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface), NULL); - - impls = (InterfaceImplementation *) priv->implementations->data; + impls = (ExtensionImplementation *) priv->implementations->data; for (i = 0; i < priv->implementations->len; ++i) { - if (impls[i].iface_type == interface) + if (impls[i].exten_type == exten_type) return impls[i].func (n_parameters, parameters, impls[i].user_data); } @@ -472,29 +477,31 @@ peas_object_module_create_object (PeasObjectModule *module, /** * peas_object_module_provides_object: (skip) * @module: A #PeasObjectModule. - * @interface: The #GType of the extension interface. + * @exten_type: The #GType of the extension. * - * Determines if the module provides an extension for @interface. + * Determines if the module provides an extension for @exten_type. * - * Return value: if the module provides an extension for @interface. + * Since libpeas 1.22, @exten_type can be an Abstract #GType + * and not just an Interface #GType. + * + * Return value: if the module provides an extension for @exten_type. */ gboolean peas_object_module_provides_object (PeasObjectModule *module, - GType interface) + GType exten_type) { PeasObjectModulePrivate *priv = GET_PRIV (module); guint i; - InterfaceImplementation *impls; + ExtensionImplementation *impls; g_return_val_if_fail (PEAS_IS_OBJECT_MODULE (module), FALSE); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type) || + G_TYPE_IS_ABSTRACT (exten_type), FALSE); - if (interface != PEAS_TYPE_PLUGIN_LOADER) - g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface), FALSE); - - impls = (InterfaceImplementation *) priv->implementations->data; + impls = (ExtensionImplementation *) priv->implementations->data; for (i = 0; i < priv->implementations->len; ++i) { - if (impls[i].iface_type == interface) + if (impls[i].exten_type == exten_type) return TRUE; } @@ -578,8 +585,8 @@ peas_object_module_get_library (PeasObjectModule *module) /** * peas_object_module_register_extension_factory: * @module: Your plugin's #PeasObjectModule. - * @iface_type: The #GType of the extension interface you implement. - * @factory_func: The #PeasFactoryFunc that will create the @iface_type + * @exten_type: The #GType of the extension you implement. + * @factory_func: The #PeasFactoryFunc that will create the @exten_type * instance when requested. * @user_data: Data to pass to @func calls. * @destroy_func: A #GDestroyNotify for @user_data. @@ -592,27 +599,29 @@ peas_object_module_get_library (PeasObjectModule *module) * creating native types which cannot be instantiated correctly using * g_object_new(). For other uses, you will usually prefer relying on * peas_object_module_register_extension_type(). + * + * Since libpeas 1.22, @exten_type can be an Abstract #GType + * and not just an Interface #GType. */ void peas_object_module_register_extension_factory (PeasObjectModule *module, - GType iface_type, + GType exten_type, PeasFactoryFunc factory_func, gpointer user_data, GDestroyNotify destroy_func) { PeasObjectModulePrivate *priv = GET_PRIV (module); - InterfaceImplementation impl = { iface_type, factory_func, user_data, destroy_func }; + ExtensionImplementation impl = { exten_type, factory_func, user_data, destroy_func }; g_return_if_fail (PEAS_IS_OBJECT_MODULE (module)); - g_return_if_fail (!peas_object_module_provides_object (module, iface_type)); + g_return_if_fail (G_TYPE_IS_INTERFACE (exten_type) || + G_TYPE_IS_ABSTRACT (exten_type)); + g_return_if_fail (!peas_object_module_provides_object (module, exten_type)); g_return_if_fail (factory_func != NULL); - if (iface_type != PEAS_TYPE_PLUGIN_LOADER) - g_return_if_fail (G_TYPE_IS_INTERFACE (iface_type)); - g_array_append_val (priv->implementations, impl); - g_debug ("Registered extension for type '%s'", g_type_name (iface_type)); + g_debug ("Registered extension for type '%s'", g_type_name (exten_type)); } static GObject * @@ -620,15 +629,15 @@ create_gobject_from_type (guint n_parameters, GParameter *parameters, gpointer user_data) { - GType exten_type = GPOINTER_TO_SIZE (user_data); + GType impl_type = GPOINTER_TO_SIZE (user_data); /* We should be called with a "plugin-info" property appended * to the parameters. Let's get rid of it if the actual type * doesn't have such a property as it would cause a warning. */ - if ((exten_type & TYPE_MISSING_PLUGIN_INFO_PROPERTY) != 0) + if ((impl_type & TYPE_MISSING_PLUGIN_INFO_PROPERTY) != 0) { - exten_type &= ~TYPE_MISSING_PLUGIN_INFO_PROPERTY; + impl_type &= ~TYPE_MISSING_PLUGIN_INFO_PROPERTY; if (n_parameters > 0) { @@ -642,44 +651,45 @@ create_gobject_from_type (guint n_parameters, } } - return G_OBJECT (g_object_newv (exten_type, n_parameters, parameters)); + return G_OBJECT (g_object_newv (impl_type, n_parameters, parameters)); } /** * peas_object_module_register_extension_type: * @module: Your plugin's #PeasObjectModule. - * @iface_type: The #GType of the extension interface you implement. - * @extension_type: The #GType of your implementation of @iface_type. + * @exten_type: The #GType of the extension you implement. + * @impl_type: The #GType of your implementation of @exten_type. * - * Register an extension type which implements the extension interface - * @iface_type. + * Register @impl_type as an extension which implements @extension_type. + * + * Since libpeas 1.22, @exten_type can be an Abstract #GType + * and not just an Interface #GType. */ void peas_object_module_register_extension_type (PeasObjectModule *module, - GType iface_type, - GType extension_type) + GType exten_type, + GType impl_type) { GObjectClass *cls; GParamSpec *pspec; g_return_if_fail (PEAS_IS_OBJECT_MODULE (module)); - g_return_if_fail (!peas_object_module_provides_object (module, iface_type)); - g_return_if_fail (g_type_is_a (extension_type, iface_type)); - - if (iface_type != PEAS_TYPE_PLUGIN_LOADER) - g_return_if_fail (G_TYPE_IS_INTERFACE (iface_type)); + g_return_if_fail (G_TYPE_IS_INTERFACE (exten_type) || + G_TYPE_IS_ABSTRACT (exten_type)); + g_return_if_fail (!peas_object_module_provides_object (module, exten_type)); + g_return_if_fail (g_type_is_a (impl_type, exten_type)); - cls = g_type_class_ref (extension_type); + cls = g_type_class_ref (impl_type); pspec = g_object_class_find_property (cls, "plugin-info"); /* Avoid checking for this each time in the factory function */ if (pspec == NULL || pspec->value_type != PEAS_TYPE_PLUGIN_INFO) - extension_type |= TYPE_MISSING_PLUGIN_INFO_PROPERTY; + impl_type |= TYPE_MISSING_PLUGIN_INFO_PROPERTY; peas_object_module_register_extension_factory (module, - iface_type, + exten_type, create_gobject_from_type, - GSIZE_TO_POINTER (extension_type), + GSIZE_TO_POINTER (impl_type), NULL); g_type_class_unref (cls); diff --git a/libpeas/peas-object-module.h b/libpeas/peas-object-module.h index 70a0265..08c5d6b 100644 --- a/libpeas/peas-object-module.h +++ b/libpeas/peas-object-module.h @@ -95,11 +95,11 @@ PeasObjectModule *peas_object_module_new_embedded (const gchar const gchar *symbol); GObject *peas_object_module_create_object (PeasObjectModule *module, - GType interface, + GType exten_type, guint n_parameters, GParameter *parameters); gboolean peas_object_module_provides_object (PeasObjectModule *module, - GType interface); + GType exten_type); const gchar *peas_object_module_get_path (PeasObjectModule *module); const gchar *peas_object_module_get_module_name (PeasObjectModule *module); @@ -109,14 +109,14 @@ GModule *peas_object_module_get_library (PeasObjectModule void peas_object_module_register_extension_factory (PeasObjectModule *module, - GType iface_type, + GType exten_type, PeasFactoryFunc factory_func, gpointer user_data, GDestroyNotify destroy_func); void peas_object_module_register_extension_type (PeasObjectModule *module, - GType iface_type, - GType extension_type); + GType exten_type, + GType impl_type); G_END_DECLS diff --git a/libpeas/peas-utils.c b/libpeas/peas-utils.c index 1051d20..7d3bd91 100644 --- a/libpeas/peas-utils.c +++ b/libpeas/peas-utils.c @@ -91,6 +91,34 @@ add_all_prerequisites (GType iface_type, g_free (prereq); } +static GPtrArray * +find_base_type_and_interfaces (GType exten_type, + GType *base_type) +{ + GPtrArray *ifaces; + GType *interfaces; + gint i; + + ifaces = g_ptr_array_new (); + g_ptr_array_set_free_func (ifaces, + (GDestroyNotify) g_type_default_interface_unref); + + if (G_TYPE_IS_INTERFACE (exten_type)) + { + add_all_prerequisites (exten_type, base_type, ifaces); + return ifaces; + } + + interfaces = g_type_interfaces (exten_type, NULL); + for (i = 0; interfaces[i] != G_TYPE_INVALID; ++i) + add_all_prerequisites (exten_type, base_type, ifaces); + + *base_type = exten_type; + + g_free (interfaces); + return ifaces; +} + static GParamSpec * find_param_spec_for_prerequisites (const gchar *name, GObjectClass *klass, @@ -113,7 +141,7 @@ find_param_spec_for_prerequisites (const gchar *name, } gboolean -peas_utils_valist_to_parameter_list (GType iface_type, +peas_utils_valist_to_parameter_list (GType exten_type, const gchar *first_property, va_list args, GParameter **params, @@ -125,12 +153,10 @@ peas_utils_valist_to_parameter_list (GType iface_type, const gchar *name; guint n_allocated_params; - g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface_type), FALSE); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type) || + G_TYPE_IS_OBJECT (exten_type), FALSE); - ifaces = g_ptr_array_new (); - g_ptr_array_set_free_func (ifaces, - (GDestroyNotify) g_type_default_interface_unref); - add_all_prerequisites (iface_type, &base_type, ifaces); + ifaces = find_base_type_and_interfaces (exten_type, &base_type); if (base_type != G_TYPE_INVALID) klass = g_type_class_ref (base_type); @@ -150,7 +176,7 @@ peas_utils_valist_to_parameter_list (GType iface_type, if (!pspec) { g_warning ("%s: type '%s' has no property named '%s'", - G_STRFUNC, g_type_name (iface_type), name); + G_STRFUNC, g_type_name (exten_type), name); goto error; } diff --git a/libpeas/peas-utils.h b/libpeas/peas-utils.h index adca711..5a19ba0 100644 --- a/libpeas/peas-utils.h +++ b/libpeas/peas-utils.h @@ -27,7 +27,7 @@ #define PEAS_UTILS_C_LOADER_ID 0 #define PEAS_UTILS_N_LOADERS 4 -gboolean peas_utils_valist_to_parameter_list (GType iface_type, +gboolean peas_utils_valist_to_parameter_list (GType exten_type, const gchar *first_property, va_list var_args, GParameter **params, diff --git a/tests/libpeas/introspection/Makefile.am b/tests/libpeas/introspection/Makefile.am index 930851b..3ea3758 100644 --- a/tests/libpeas/introspection/Makefile.am +++ b/tests/libpeas/introspection/Makefile.am @@ -13,6 +13,8 @@ libintrospection_1_0_la_LIBADD = \ $(top_builddir)/libpeas/libpeas-1.0.la libintrospection_1_0_la_SOURCES = \ + introspection-abstract.c \ + introspection-abstract.h \ introspection-base.c \ introspection-base.h \ introspection-callable.c \ diff --git a/tests/libpeas/introspection/introspection-abstract.c b/tests/libpeas/introspection/introspection-abstract.c new file mode 100644 index 0000000..0363d0a --- /dev/null +++ b/tests/libpeas/introspection/introspection-abstract.c @@ -0,0 +1,132 @@ +/* + * introspection-abstract.h + * This file is part of libpeas + * + * Copyright (C) 2017 Garrett Regier + * + * libpeas is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libpeas 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "introspection-abstract.h" + +typedef struct { + gint value; +} IntrospectionAbstractPrivate; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (IntrospectionAbstract, + introspection_abstract, + PEAS_TYPE_EXTENSION_BASE) + +#define GET_PRIV(o) \ + (introspection_abstract_get_instance_private (o)) + +enum { + PROP_0, + PROP_ABSTRACT_PROPERTY, + N_PROPERTIES +}; + +static GParamSpec *properties[N_PROPERTIES] = { NULL }; + +static void +introspection_abstract_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + IntrospectionAbstract *abstract = INTROSPECTION_ABSTRACT (object); + IntrospectionAbstractPrivate *priv = GET_PRIV (abstract); + + switch (prop_id) + { + case PROP_ABSTRACT_PROPERTY: + g_value_set_int (value, priv->value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +introspection_abstract_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + IntrospectionAbstract *abstract = INTROSPECTION_ABSTRACT (object); + IntrospectionAbstractPrivate *priv = GET_PRIV (abstract); + + switch (prop_id) + { + case PROP_ABSTRACT_PROPERTY: + priv->value = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +introspection_abstract_class_init (IntrospectionAbstractClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = introspection_abstract_get_property; + object_class->set_property = introspection_abstract_set_property; + + properties[PROP_ABSTRACT_PROPERTY] = + g_param_spec_int ("abstract-property", + "Abstract Property", + "The IntrospectionAbstract", + G_MININT, + G_MAXINT, + -1, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, N_PROPERTIES, properties); +} + +static void +introspection_abstract_init (IntrospectionAbstract *prereq) +{ +} + +gint +introspection_abstract_get_value (IntrospectionAbstract *abstract) +{ + IntrospectionAbstractPrivate *priv = GET_PRIV (abstract); + + g_return_val_if_fail (INTROSPECTION_IS_ABSTRACT (abstract), -1); + + return priv->value; +} + +void +introspection_abstract_set_value (IntrospectionAbstract *abstract, + gint value) +{ + IntrospectionAbstractPrivate *priv = GET_PRIV (abstract); + + g_return_if_fail (INTROSPECTION_IS_ABSTRACT (abstract)); + + priv->value = value; +} diff --git a/tests/libpeas/introspection/introspection-abstract.h b/tests/libpeas/introspection/introspection-abstract.h new file mode 100644 index 0000000..bfff2c4 --- /dev/null +++ b/tests/libpeas/introspection/introspection-abstract.h @@ -0,0 +1,60 @@ +/* + * introspection-abstract.h + * This file is part of libpeas + * + * Copyright (C) 2017 Garrett Regier + * + * libpeas is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libpeas 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __INTROSPECTION_ABSTRACT_H__ +#define __INTROSPECTION_ABSTRACT_H__ + +#include <libpeas/peas.h> + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define INTROSPECTION_TYPE_ABSTRACT (introspection_abstract_get_type ()) +#define INTROSPECTION_ABSTRACT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INTROSPECTION_TYPE_ABSTRACT, IntrospectionAbstract)) +#define INTROSPECTION_ABSTRACT_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), INTROSPECTION_TYPE_ABSTRACT, IntrospectionAbstractClass)) +#define INTROSPECTION_IS_ABSTRACT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INTROSPECTION_TYPE_ABSTRACT)) +#define INTROSPECTION_ABSTRACT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INTROSPECTION_TYPE_ABSTRACT, IntrospectionAbstractClass)) + +typedef struct _IntrospectionAbstract IntrospectionAbstract; +typedef struct _IntrospectionAbstractClass IntrospectionAbstractClass; + +struct _IntrospectionAbstract { + PeasExtensionBase parent; +}; + +struct _IntrospectionAbstractClass { + PeasExtensionBaseClass parent_class; +}; + +/* + * Public methods + */ +GType introspection_abstract_get_type (void) G_GNUC_CONST; + +gint introspection_abstract_get_value (IntrospectionAbstract *abstract); +void introspection_abstract_set_value (IntrospectionAbstract *abstract, + gint value); + +G_END_DECLS + +#endif /* __INTROSPECTION_ABSTRACT_H__ */ diff --git a/tests/libpeas/plugins/extension-c/Makefile.am b/tests/libpeas/plugins/extension-c/Makefile.am index 751b68b..24effac 100644 --- a/tests/libpeas/plugins/extension-c/Makefile.am +++ b/tests/libpeas/plugins/extension-c/Makefile.am @@ -12,7 +12,9 @@ noinst_LTLIBRARIES = \ libextension-c-missing-symbol.la libextension_c_la_SOURCES = \ - extension-c-plugin.c \ + extension-c-abstract.c \ + extension-c-abstract.h \ + extension-c-plugin.c \ extension-c-plugin.h libextension_c_la_LDFLAGS = $(TEST_PLUGIN_LIBTOOL_FLAGS) diff --git a/tests/libpeas/plugins/extension-c/extension-c-abstract.c b/tests/libpeas/plugins/extension-c/extension-c-abstract.c new file mode 100644 index 0000000..c6f767e --- /dev/null +++ b/tests/libpeas/plugins/extension-c/extension-c-abstract.c @@ -0,0 +1,55 @@ +/* + * extension-c-abstract.c + * This file is part of libpeas + * + * Copyright (C) 2017 - Garrett Regier + * + * libpeas is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libpeas 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib-object.h> + +#include <libpeas/peas.h> + +#include "extension-c-abstract.h" + +G_DEFINE_DYNAMIC_TYPE (TestingExtensionCAbstract, + testing_extension_c_abstract, + INTROSPECTION_TYPE_ABSTRACT) + +static void +testing_extension_c_abstract_init (TestingExtensionCAbstract *abstract) +{ +} + +static void +testing_extension_c_abstract_class_init (TestingExtensionCAbstractClass *klass) +{ +} + +static void +testing_extension_c_abstract_class_finalize (TestingExtensionCAbstractClass *klass) +{ +} + +void +testing_extension_c_abstract_register (GTypeModule *module) +{ + testing_extension_c_abstract_register_type (module); +} diff --git a/tests/libpeas/plugins/extension-c/extension-c-abstract.h b/tests/libpeas/plugins/extension-c/extension-c-abstract.h new file mode 100644 index 0000000..57d35c3 --- /dev/null +++ b/tests/libpeas/plugins/extension-c/extension-c-abstract.h @@ -0,0 +1,52 @@ +/* + * extension-c-abstract.h + * This file is part of libpeas + * + * Copyright (C) 2017 - Garrett Regier + * + * libpeas is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libpeas 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __EXTENSION_C_ABSTRACT_H__ +#define __EXTENSION_C_ABSTRACT_H__ + +#include "introspection-abstract.h" + +G_BEGIN_DECLS + +#define TESTING_TYPE_EXTENSION_C_ABSTRACT (testing_extension_c_abstract_get_type ()) +#define TESTING_EXTENSION_C_ABSTRACT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TESTING_TYPE_EXTENSION_C_ABSTRACT, TestingExtensionCAbstract)) +#define TESTING_EXTENSION_C_ABSTRACT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TESTING_TYPE_EXTENSION_C_ABSTRACT, TestingExtensionCAbstract)) +#define TESTING_IS_EXTENSION_C_ABSTRACT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TESTING_TYPE_EXTENSION_C_ABSTRACT)) +#define TESTING_IS_EXTENSION_C_ABSTRACT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TESTING_TYPE_EXTENSION_C_ABSTRACT)) +#define TESTING_EXTENSION_C_ABSTRACT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TESTING_TYPE_EXTENSION_C_ABSTRACT, TestingExtensionCAbstractClass)) + +typedef struct _TestingExtensionCAbstract TestingExtensionCAbstract; +typedef struct _TestingExtensionCAbstractClass TestingExtensionCAbstractClass; + +struct _TestingExtensionCAbstract { + IntrospectionAbstract parent_instance; +}; + +struct _TestingExtensionCAbstractClass { + IntrospectionAbstractClass parent_class; +}; + +GType testing_extension_c_abstract_get_type (void) G_GNUC_CONST; +void testing_extension_c_abstract_register (GTypeModule *module); + +G_END_DECLS + +#endif /* __EXTENSION_C_ABSTRACT_H__ */ diff --git a/tests/libpeas/plugins/extension-c/extension-c-plugin.c b/tests/libpeas/plugins/extension-c/extension-c-plugin.c index 3125de8..1e4b283 100644 --- a/tests/libpeas/plugins/extension-c/extension-c-plugin.c +++ b/tests/libpeas/plugins/extension-c/extension-c-plugin.c @@ -29,11 +29,13 @@ #include <libpeas/peas.h> +#include "introspection-abstract.h" #include "introspection-base.h" #include "introspection-callable.h" #include "introspection-has-prerequisite.h" #include "introspection-prerequisite.h" +#include "extension-c-abstract.h" #include "extension-c-plugin.h" /* Used by the local linkage test */ @@ -175,9 +177,14 @@ testing_extension_c_plugin_class_finalize (TestingExtensionCPluginClass *klass) G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module) { + testing_extension_c_abstract_register (G_TYPE_MODULE (module)); testing_extension_c_plugin_register_type (G_TYPE_MODULE (module)); peas_object_module_register_extension_type (module, + INTROSPECTION_TYPE_ABSTRACT, + TESTING_TYPE_EXTENSION_C_ABSTRACT); + + peas_object_module_register_extension_type (module, INTROSPECTION_TYPE_BASE, TESTING_TYPE_EXTENSION_C_PLUGIN); peas_object_module_register_extension_type (module, diff --git a/tests/libpeas/plugins/extension-lua/extension-lua51.lua b/tests/libpeas/plugins/extension-lua/extension-lua51.lua index 69df5f7..66ee571 100644 --- a/tests/libpeas/plugins/extension-lua/extension-lua51.lua +++ b/tests/libpeas/plugins/extension-lua/extension-lua51.lua @@ -22,6 +22,10 @@ local Introspection = lgi.Introspection local Peas = lgi.Peas +local ExtensionLuaAbstract = + Introspection.Abstract:derive('ExtensionLuaAbstract') + + local ExtensionLuaPlugin = Introspection.Prerequisite:derive('ExtensionLuaPlugin', { Peas.Activatable, @@ -100,6 +104,6 @@ assert(pcall(function() __STRICT = true end)) -return { ExtensionLuaPlugin } +return { ExtensionLuaAbstract, ExtensionLuaPlugin } -- ex:set ts=4 et sw=4 ai: diff --git a/tests/libpeas/plugins/extension-python/extension-py.py.in b/tests/libpeas/plugins/extension-python/extension-py.py.in index d5ea6fa..59070c4 100644 --- a/tests/libpeas/plugins/extension-python/extension-py.py.in +++ b/tests/libpeas/plugins/extension-python/extension-py.py.in @@ -24,7 +24,11 @@ import threading from gi.repository import GObject, Introspection, Peas -__all__ = [ 'ExtensionPythonPlugin' ] +__all__ = [ 'ExtensionPythonAbstract', 'ExtensionPythonPlugin' ] + + +class ExtensionPythonAbstract(Introspection.Abstract): + pass class ExtensionPythonPlugin(Introspection.Prerequisite, Peas.Activatable, diff --git a/tests/libpeas/testing/testing-extension.c b/tests/libpeas/testing/testing-extension.c index 60e88f4..e00588b 100644 --- a/tests/libpeas/testing/testing-extension.c +++ b/tests/libpeas/testing/testing-extension.c @@ -33,6 +33,7 @@ #include "testing.h" #include "testing-extension.h" +#include "introspection-abstract.h" #include "introspection-base.h" #include "introspection-callable.h" #include "introspection-has-prerequisite.h" @@ -264,6 +265,29 @@ test_extension_get_settings (PeasEngine *engine, g_object_unref (extension); } +static void +test_extension_abstract (PeasEngine *engine, + PeasPluginInfo *info) +{ + PeasExtension *extension; + IntrospectionAbstract *abstract; + + g_assert (peas_engine_load_plugin (engine, info)); + + extension = peas_engine_create_extension (engine, info, + INTROSPECTION_TYPE_ABSTRACT, + "abstract-property", 47, + NULL); + + abstract = INTROSPECTION_ABSTRACT (extension); + + g_assert_cmpint (introspection_abstract_get_value (abstract), ==, 47); + introspection_abstract_set_value (abstract, -22); + g_assert_cmpint (introspection_abstract_get_value (abstract), ==, -22); + + g_object_unref (extension); +} + static gint run_in_multiple_threads (GFunc func, gpointer user_data) @@ -479,6 +503,30 @@ test_extension_call_multi_args (PeasEngine *engine, g_object_unref (extension); } +static void +test_extension_call_abstract (PeasEngine *engine, + PeasPluginInfo *info) +{ + PeasExtension *extension; + gint value = 0; + + g_assert (peas_engine_load_plugin (engine, info)); + + extension = peas_engine_create_extension (engine, info, + INTROSPECTION_TYPE_ABSTRACT, + "abstract-property", 47, + NULL); + + g_assert (peas_extension_call (extension, "get_value", &value)); + g_assert_cmpint (value, ==, 47); + + g_assert (peas_extension_call (extension, "set_value", -22)); + g_assert (peas_extension_call (extension, "get_value", &value)); + g_assert_cmpint (value, ==, -22); + + g_object_unref (extension); +} + #define _EXTENSION_TEST(loader, path, ftest) \ G_STMT_START { \ gchar *full_path = g_strdup_printf (EXTENSION_TEST_NAME (%s, "%s"), \ @@ -533,6 +581,8 @@ testing_extension_basic (const gchar *loader_) _EXTENSION_TEST (loader, "plugin-info", plugin_info); _EXTENSION_TEST (loader, "get-settings", get_settings); + _EXTENSION_TEST (loader, "abstract", abstract); + _EXTENSION_TEST (loader, "multiple-threads/global-loaders", multiple_threads_global_loaders); _EXTENSION_TEST (loader, "multiple-threads/nonglobal-loaders", @@ -553,6 +603,7 @@ testing_extension_callable (const gchar *loader) _EXTENSION_TEST (loader, "call-with-return", call_with_return); _EXTENSION_TEST (loader, "call-single-arg", call_single_arg); _EXTENSION_TEST (loader, "call-multi-args", call_multi_args); + _EXTENSION_TEST (loader, "call-abstract", call_abstract); } void |