如何创建nautilus C扩展 [英] How to create nautilus C extensions

查看:294
本文介绍了如何创建nautilus C扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在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)
{
}

静态GType provider_types [1];

静态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);
/ * ...添加接口... * /
}

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),
_(来自Foo扩展的信息)); * /
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)
{
/ *任何模块关闭* /
}

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 - 共享foo_extension.o -o foo_extension.so $(pkg-config libnautilus-extension --libs --cflags)

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

copy.org中的副本。 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_complete 句柄以及 cancel_update 界面。查看文档其副本在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 *提供程序;
NautilusFileInfo *文件;
int operation_handle;
gboolean已取消;
} 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 *提供程序,
NautilusFileInfo *文件,
GClosure * update_complete,
NautilusOperationHandle **句柄);

/ *接口* /
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;

$ b / *扩展名* /
static void foo_extension_class_init(FooExtensionClass * class)
{
}

static void foo_extension_instance_init(FooExtension * img)
{
}

静态GType provider_types [1];

静态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);
$ b / * ...添加接口... * /
g_type_module_add_interface(module,
foo_extension_type,
NAUTILUS_TYPE_COLUMN_PROVIDER,
& column_provider_iface_info);

g_type_module_add_interface(模块,
foo_extension_type,
NAUTILUS_TYPE_INFO_PROVIDER,
& info_provider_iface_info);
}

GType foo_extension_get_type(void)
{
return foo_extension_type;

$ b $ *列接口* /
静态GList * foo_extension_get_columns(NautilusColumnProvider *提供程序)
{
NautilusColumn *列;
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;
}
$ b $ * / Info接口* /
静态NautilusOperationResult
foo_extension_update_file_info(NautilusInfoProvider *提供程序,
NautilusFileInfo *文件,
GClosure * update_complete ,
NautilusOperationHandle **句柄)
{
char * data;
$ b $ *检查我们以前是否缓存过文件info * /
data = g_object_get_data(G_OBJECT(file),foo_extension_data);

/ *获取并提供与该列相关的信息。
如果操作速度不够快,我们应该使用参数
update_complete并处理异步操作。 * /
if(!data){
data = g_strdup(Foo);
}

nautilus_file_info_add_string_attribute(file,
FooExtension :: foo_data,
data);
返回NAUTILUS_OPERATION_COMPLETE;

$ b $ *扩展初始化* /
void nautilus_module_initialize(GTypeModule * module)
{
foo_extension_register_type(module);
provider_types [0] = foo_extension_get_type();
}

void nautilus_module_shutdown(void)
{
/ *任何模块关闭* /
}

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 
$鹦鹉螺

请注意,您没有使用 -q 选项用于 quit



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

  $ strace -e trace =打开鹦鹉螺

看看哪些库和文件 Nautilus 正在加载/打开。



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


I'm trying to create a Nautilus extension in C, but there are just Python examples and helps.

Almost no documentation and literally no examples, but just some complete extensions which are long and hard to understand for a beginner.

I need just a simple sample code that creates a new column in Nautilus's list view. How to write and compile it.

The code I've tried is:

#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);
}

and I've built it with:

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)

and I copied it into /usr/lib/nautilus/extensions-2.0/, then I tried nautilus -q but it doesn't work.

解决方案

You can also retrieve the documentation pointed in Nautilus Extension's wiki from the copy in archive.org. The copy in archive.org has examples in C.

EDIT: I added a complete working example, as well as as an explanation of the missing parts in your code.

You are missing two things:

  1. Add the interfaces. For the column provider would be foo_extension_column_provider_iface_init, and there you need to associate the link the interfaces expected with your implementation. In this particular case get_columns.
  2. With the previous one, you would get only a column but with unknown value for each file. Therefore, you have to use the InfoProvider, too. In particular, the interface update_file_info. In that interface you can associate the attribute for your column with each file through nautilus_file_info_add_string_attribute.

Below you have a working example. Beware NautilusFileInfoProvider is part of Nautilus' asynchronous IO system. Hence, if the operations are slow, you will block Nautilus. In the example below I just set a fixed string per file ("Foo"). However, if you need to collect other information, you should implement also the arguments update_complete and handle, and the cancel_update interface. Check the 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);
}

To compile it:

$ 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)

For testing the extension, first you need to stop any running instance of nautilus and re-launch nautilus. That is:

$ nautilus -q
$ nautilus 

Note that is without the option -q you used, which is for quit.

If you would like to check if Nautilus is loading your extension, you can use strace as follow:

$ strace -e trace=open nautilus

And see what libraries and files Nautilus is loading/opening.

While working in your extension, instead of copying the extension file in [libdir]/nautilus/extensions-3.0, you can create a symlink to your working directory. If you are using Nautilus 2.x, use [libdir]/nautilus/extensions-2.0 instead.

这篇关于如何创建nautilus C扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆