如何创建nautilus C扩展

时间:2012-03-12 21:52:55

标签: c gtk shared-libraries gnome nautilus

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

几乎没有文档,几乎没有示例,只是一些完整的扩展,对于初学者来说很长很难理解。

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

我尝试的代码是:

#include <libnautilus-extension/nautilus-column-provider.h>

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,但它不起作用。

1 个答案:

答案 0 :(得分:8)

您还可以从Nautilus Extension's wiki检索the copy in archive.org中指向的文档。 archive.org中的副本包含C中的示例。

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

你遗漏了两件事:

  1. 添加界面。对于列提供程序, foo_extension_column_provider_iface_init ,您需要将预期接口的链接与您的实现相关联。在这种特殊情况下 get_columns
  2. 使用上一个,您只能获得一列,但每个文件的值都是未知的。因此,您还必须使用 InfoProvider 。特别是,接口 update_file_info 。在该界面中,您可以通过 nautilus_file_info_add_string_attribute 将列的属性与每个文件相关联。
  3. 下面是一个有效的例子。注意 NautilusFileInfoProvider 是Nautilus异步IO系统的一部分。因此,如果操作很慢,您将阻止Nautilus。在下面的示例中,我只为每个文件设置一个固定的字符串(“ Foo ”)。但是,如果您需要收集其他信息,还应实施参数 update_complete 句柄以及 cancel_update 界面。查看documentation whose copy is available in archive.org

    #include <libnautilus-extension/nautilus-column-provider.h>
    #include <libnautilus-extension/nautilus-info-provider.h>
    
    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

相关问题