Как создать расширения nautilus C

Я пытаюсь создать расширение Nautilus в C, но есть только примеры 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 но он не работает.

Вы также можете получить документацию, указанную в вики Nautilus Extension, из копии в archive.org . У копии в archive.org есть примеры в C.

EDIT: Я добавил полный рабочий пример, а также объяснение недостающих частей в вашем коде.

Вам не хватает двух вещей:

  1. Добавьте интерфейсы. Для поставщика столбцов будет foo_extension_column_provider_iface_init , и вам нужно связать ссылку, которую ожидали интерфейсы с вашей реализацией. В этом конкретном случае get_columns .
  2. С предыдущим вы получите только столбец, но с неизвестным значением для каждого файла. Поэтому вам также нужно использовать InfoProvider . В частности, интерфейс update_file_info . В этом интерфейсе вы можете связать атрибут для своего столбца с каждым файлом через nautilus_file_info_add_string_attribute .

Ниже приведен рабочий пример. Остерегайтесь NautilusFileInfoProvider является частью асинхронной системы ввода-вывода Nautilus. Следовательно, если операции будут медленными, вы заблокируете Nautilus. В приведенном ниже примере я просто установил фиксированную строку в файле (« Foo »). Однако, если вам нужно собрать другую информацию, вы должны также реализовать аргументы update_complete и handle , а также интерфейс cancel_update . Проверьте документацию, копия которой имеется в архиве.

 #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 .