如何创建nautilus C扩展

我正在尝试在C中创建Nautilus扩展,但只有Python示例和帮助。

几乎没有文档和字面上没有示例,但只是一些完整的扩展,这些扩展很长,很难为初学者理解。

我只需要一个简单的示例代码,在Nautilus的列表视图中创建一个新列。 如何编写和编译它。

我试过的代码是:

#include  typedef struct _FooExtension FooExtension; typedef struct _FooExtensionClass FooExtensionClass; struct _FooExtension { GObject parent_slot; }; struct _FooExtensionClass { GObjectClass parent_slot; }; static void foo_extension_class_init (FooExtensionClass *class); static void foo_extension_instance_init (FooExtension *img); static void foo_extension_class_init(FooExtensionClass *class) { } static void foo_extension_instance_init(FooExtension *img) { } static GType provider_types[1]; static GType foo_extension_type; static void foo_extension_register_type(GTypeModule *module) { static const GTypeInfo info = { sizeof(FooExtensionClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) foo_extension_class_init, NULL, NULL, sizeof (FooExtension), 0, (GInstanceInitFunc) foo_extension_instance_init, }; foo_extension_type = g_type_module_register_type(module, G_TYPE_OBJECT, "FooExtension", &info, 0); /* ... add interfaces ... */ } GType foo_extension_get_type(void) { return foo_extension_type; } static GList *foo_extension_get_columns(NautilusColumnProvider *provider) { NautilusColumn *column; GList *ret; column = nautilus_column_new("FooExtension::foo_data_column", "FooExtension::foo_data", "Foo Data", "Foo Description"); /* _("Foo Data"), _("Information from the Foo Extension"));*/ ret = g_list_append(NULL, column); return ret; } void nautilus_module_initialize (GTypeModule *module) { foo_extension_register_type(module); provider_types[0] = foo_extension_get_type(); } void nautilus_module_shutdown(void) { /* Any module-specific shutdown */ } void nautilus_module_list_types (const GType **types, int *num_types) { *types = provider_types; *num_types = G_N_ELEMENTS (provider_types); } 

我用它构建了它:

 gcc-c foo_extension.c -o foo_extension.o -fPIC $(pkg-config libnautilus-extension --libs --cflags) gcc -shared foo_extension.o -o foo_extension.so $(pkg-config libnautilus-extension --libs --cflags) 

然后我把它复制到/usr/lib/nautilus/extensions-2.0/ ,然后我尝试了nautilus -q但它不起作用。

您还可以从archive.org中的副本检索Nautilus Extension的wiki中指向的文档。 archive.org中的副本在C中有示例。

编辑:我添加了一个完整的工作示例,以及代码中缺少部分的解释。

你错过了两件事:

  1. 添加接口。 对于列提供程序,将为foo_extension_column_provider_iface_init ,您需要将预期接口的链接与您的实现相关联。 在这种特殊情况下get_columns
  2. 使用前一个,您将只获得一个列,但每个文件的值都是未知的。 因此,您也必须使用InfoProvider 。 特别是接口update_file_info 。 在该接口中,您可以通过nautilus_file_info_add_string_attribute将列的属性与每个文件相关联。

下面你有一个工作的例子。 注意NautilusFileInfoProvider是Nautilus异步IO系统的一部分。 因此,如果操作很慢,您将阻止Nautilus。 在下面的示例中,我只为每个文件设置一个固定的字符串(“ Foo ”)。 但是,如果需要收集其他信息,还应该实现参数update_completehandle以及cancel_update接口。 查看archive.org中提供副本的文档

 #include  #include  typedef struct _FooExtension FooExtension; typedef struct _FooExtensionClass FooExtensionClass; typedef struct { GClosure *update_complete; NautilusInfoProvider *provider; NautilusFileInfo *file; int operation_handle; gboolean cancelled; } UpdateHandle; struct _FooExtension { GObject parent_slot; }; struct _FooExtensionClass { GObjectClass parent_slot; }; static void foo_extension_class_init (FooExtensionClass *class); static void foo_extension_instance_init (FooExtension *img); static GList *foo_extension_get_columns (NautilusColumnProvider *provider); static NautilusOperationResult foo_extension_update_file_info ( NautilusInfoProvider *provider, NautilusFileInfo *file, GClosure *update_complete, NautilusOperationHandle **handle); /* Interfaces */ static void foo_extension_column_provider_iface_init (NautilusColumnProviderIface *iface) { iface->get_columns = foo_extension_get_columns; return; } static void foo_extension_info_provider_iface_init (NautilusInfoProviderIface *iface) { iface->update_file_info = foo_extension_update_file_info; return; } /* Extension */ static void foo_extension_class_init(FooExtensionClass *class) { } static void foo_extension_instance_init(FooExtension *img) { } static GType provider_types[1]; static GType foo_extension_type; static void foo_extension_register_type(GTypeModule *module) { static const GTypeInfo info = { sizeof(FooExtensionClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) foo_extension_class_init, NULL, NULL, sizeof (FooExtension), 0, (GInstanceInitFunc) foo_extension_instance_init, }; static const GInterfaceInfo column_provider_iface_info = { (GInterfaceInitFunc) foo_extension_column_provider_iface_init, NULL, NULL }; static const GInterfaceInfo info_provider_iface_info = { (GInterfaceInitFunc) foo_extension_info_provider_iface_init, NULL, NULL }; foo_extension_type = g_type_module_register_type(module, G_TYPE_OBJECT, "FooExtension", &info, 0); /* ... add interfaces ... */ g_type_module_add_interface (module, foo_extension_type, NAUTILUS_TYPE_COLUMN_PROVIDER, &column_provider_iface_info); g_type_module_add_interface (module, foo_extension_type, NAUTILUS_TYPE_INFO_PROVIDER, &info_provider_iface_info); } GType foo_extension_get_type(void) { return foo_extension_type; } /* Column interfaces */ static GList *foo_extension_get_columns(NautilusColumnProvider *provider) { NautilusColumn *column; GList *ret; column = nautilus_column_new ("FooExtension::foo_data_column", "FooExtension::foo_data", "Foo Data", "Foo Description"); ret = g_list_append(NULL, column); return ret; } /* Info interfaces */ static NautilusOperationResult foo_extension_update_file_info (NautilusInfoProvider *provider, NautilusFileInfo *file, GClosure *update_complete, NautilusOperationHandle **handle) { char *data; /* Check if we've previously cached the file info */ data = g_object_get_data (G_OBJECT (file), "foo_extension_data"); /* get and provide the information associated with the column. If the operation is not fast enough, we should use the arguments update_complete and handle for asyncrhnous operation. */ if (!data) { data = g_strdup ("Foo"); } nautilus_file_info_add_string_attribute (file, "FooExtension::foo_data", data); return NAUTILUS_OPERATION_COMPLETE; } /* Extension initialization */ void nautilus_module_initialize (GTypeModule *module) { foo_extension_register_type(module); provider_types[0] = foo_extension_get_type(); } void nautilus_module_shutdown(void) { /* Any module-specific shutdown */ } void nautilus_module_list_types (const GType **types, int *num_types) { *types = provider_types; *num_types = G_N_ELEMENTS (provider_types); } 

要编译它:

 $ gcc -c foo-extension.c -o foo-extension.o -fPIC $(pkg-config libnautilus-extension --cflags) $ gcc -shared foo-extension.o -o foo-extension.so $(pkg-config libnautilus-extension --libs) 

要测试扩展,首先需要停止任何正在运行的nautilus实例并重新启动nautilus。 那是:

 $ nautilus -q $ nautilus 

请注意,没有使用-q选项,用于退出

如果您想检查Nautilus是否正在加载您的扩展程序,您可以使用strace如下:

 $ strace -e trace=open nautilus 

并查看Nautilus正在加载/打开的库和文件。

在扩展中工作时,不是在[libdir] /nautilus/extensions-3.0中复制扩展文件,而是可以为工作目录创建符号链接。 如果您使用的是Nautilus 2.x,请改用[libdir] /nautilus/extensions-2.0