如何使用dbus glib-binding传递一个图片文件

  
 
这里主要目的:用dbus 消息来传递一个大概10K的图片文件。
 
使用Garray是比较合适的,它可以包含任何类型的数据。实际调试过程中发现:实际的消息大小是图片文件大小的4倍!这是怎么回事?难道是dbus把Garray映射成DBUS_TYPE_ARRAY,而DBUS_TYPE_ARRAY是uint32的数组。其实问题的原因就在这里:你不要在XML文件中定义uint32数组(au),而定义byte 数组(ay), 这样,你的消息体的数据与实际的图片文件大小相符。
 
 
代码如下:
 
//客户端程序
int main (int argc, char **argv)
{
    DBusGConnection *connection;
    GError *error;
    DBusGProxy *proxy;
    GArray *array;
    guint length;
    FILE *fp = NULL;
    int len;
 
    g_type_init ();
 
    error = NULL;
    connection = dbus_g_bus_get (DBUS_BUS_SESSION,
                               &error);
    if (connection == NULL)
    {
      g_printerr ("Failed to open connection to bus: %s/n",
                  error->message);
      g_error_free (error);
      exit (1);
    }
 
    proxy = dbus_g_proxy_new_for_name (connection,
                                     "com.example.SomeObject",
                                     "/com/example/SomeObject",
                                     "com.example.SomeObject");
 
    error = NULL;
 
 
//从消息中读取数据文件,并且把读取的数据写到copy-client文件中    if(!com_example_SomeObject_method1(proxy,10,&array,&length,&error))
    {
        printf("Error --- %s/n",error->message);
        return 1;
    }
 
    printf("File details... length = %d/n",length);
    error = NULL;
 
    fp = fopen("copy-client","wb");
    len = fwrite(array->data,4,array->len,fp);
    fclose(fp);
 
    return 0;
}
 
 
 
//server侧的代码:
//some-object.h
 
#ifndef __SOME_OBJECT_H__
#define __SOME_OBJECT_H__
 
#include <glib-object.h>
 
typedef struct _SomeObject SomeObject;
struct _SomeObject
{
    GObject        parent_obj;
    gint         m_a;
    gchar*        m_b;
    gfloat        m_c;
};
 
typedef struct _SomeObjectClass SomeObjectClass;
struct _SomeObjectClass
{
    GObjectClass    parent_class;
 
    /* Some useful methods may follow. */
    gboolean    (*method1)    (SomeObject *self, gint x,GArray **y,gint
 *z,GError **error);
    void        (*method2)    (SomeObject *self, gchar*);
};
 
GType    some_object_get_type ();
 
gboolean some_object_method1 (SomeObject *self, gint x,GArray **y,gint
 *z,GError **);    /* virtual */
void    some_object_method2 (SomeObject *self, gchar*);    /* virtual
 */
void    some_object_method3 (SomeObject *self, gfloat);    /*
 non-virtual */
 
 
/* Handy macros */
#define SOME_OBJECT_TYPE        (some_object_get_type ())
#define SOME_OBJECT(obj)        (G_TYPE_CHECK_INSTANCE_CAST ((obj),
 SOME_OBJECT_TYPE, SomeObject))
#define SOME_OBJECT_CLASS(c)        (G_TYPE_CHECK_CLASS_CAST ((c),
 SOME_OBJECT_TYPE, SomeObjectClass))
#define SOME_IS_OBJECT(obj)        (G_TYPE_CHECK_TYPE ((obj),
 SOME_OBJECT_TYPE))
#define SOME_IS_OBJECT_CLASS(c)        (G_TYPE_CHECK_CLASS_TYPE ((c),
 SOME_OBJECT_TYPE))
#define SOME_OBJECT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS
 ((obj), SOME_OBJECT_TYPE, SomeObjectClass))
 
#endif
// End some-object.h
 
 
 
/// some-object.c
 
#include <string.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "some-object.h"
#include "some-object-glue.h"
#include <dbus/dbus-glib-bindings.h>
#include <errno.h>
 
 
static GObjectClass *parent_class = ((void *)0);
static void some_object_init (SomeObject *self);
 
char *FILENAME = "test.jpeg";
int SIZE = 0;
 
//把图片文件test.jpeg打包到消息体中
gboolean some_object_method1_impl (SomeObject *self, gint a, GArray
 **y,gint *z,GError **error)
{
    struct stat stat_buf;
    gchar *ptr = NULL;
    FILE *fp = NULL;
    int err;
    unsigned int length = 0;
    self->m_a = a;
    g_print ("Method1: %i/n", self->m_a);
    
    *y = g_array_new(FALSE,FALSE,1);
 
    stat(FILENAME,&stat_buf);
    SIZE = stat_buf.st_size;
    ptr = g_malloc(SIZE);
    errno = 0;
    fp = fopen(FILENAME,"rb");
    err = errno;
    if(fp)
    {
        FILE *fp2 = fopen("c://copy-server","wb");
        fread(ptr,1,SIZE,fp);
        
        if(fp2)
            fwrite(ptr,1,SIZE,fp2);
        
        g_array_append_vals(*y,ptr,SIZE/4);
        *z = SIZE;    
    }
    
    fclose(fp);
    
    free(ptr);
    
    return TRUE;
}
 
void some_object_method2_impl (SomeObject *self, gchar* b)
{
    self->m_b = b;
    g_print ("Method2: %s/n", self->m_b);
}
 
 
/* Public methods. */
gboolean some_object_method1 (SomeObject *self, gint a,GArray **y,gint
 *z,GError **error)
{
    return SOME_OBJECT_GET_CLASS (self)->method1 (self, a,y,z,error);
}
 
void    some_object_method2 (SomeObject *self, gchar* b)
{
    SOME_OBJECT_GET_CLASS (self)->method2 (self, b);
}
 
void    some_object_method3 (SomeObject *self, gfloat c)
{
    self->m_c = c;
    g_print ("Method3: %f/n", self->m_c);
}
 
 
void    some_object_dispose (GObject *self)
{
    static gboolean first_run = TRUE;
 
    if (first_run)
    {
        first_run = FALSE;
        
        /* Call g_object_unref on any GObjects that we hold, but don't
 break the object */
 
        parent_class-> dispose (self);
    }
}
 
void    some_object_finalize (GObject *self)
{
    parent_class-> finalize (self);
}
 
/* Here is where we override any functions. Since we have no properties
 or even fields, none of the below are needed. */
void    some_object_class_init        (gpointer g_class, gpointer
 class_data)
{
    GObjectClass    *object_class    = G_OBJECT_CLASS (g_class);
    SomeObjectClass    *this_class    = SOME_OBJECT_CLASS (g_class);
    
    //assign value to parent class
    parent_class = g_type_class_peek_parent (g_class);
    
    //assing pointer values to the base class members
    object_class-> dispose = &some_object_dispose;
    object_class-> finalize = &some_object_finalize;
    
    //assign value to derived class members
    this_class->method1 = &some_object_method1_impl;
    this_class->method2 = &some_object_method2_impl;
 
 
  dbus_g_object_type_install_info(G_TYPE_FROM_CLASS(this_class),&dbus_glib__object_info);
}
 
void some_object_init (SomeObject *self)
{
    self->m_a = 1;
    self->m_c = 1.03f;
    self->m_b = "sumit";
}
 
GType some_object_get_type () 
{
    static GType g_define_type_id = 0; 
    if ((g_define_type_id == 0)) 
    { 
        static const GTypeInfo g_define_type_info = 
        { 
            sizeof (SomeObjectClass), 
            (GBaseInitFunc) ((void *)0), 
            (GBaseFinalizeFunc) ((void *)0), 
            (GClassInitFunc) some_object_class_init, 
            (GClassFinalizeFunc) ((void *)0), 
            ((void *)0), 
            sizeof (SomeObject), 
            0, 
            (GInstanceInitFunc) some_object_init, 
        }; 
 
        g_define_type_id = g_type_register_static 
        (
            G_TYPE_OBJECT, 
            "SomeObject", 
            &g_define_type_info, 
            (GTypeFlags) 0
        );
        
    } 
 
    return g_define_type_id; 
}
 
int main(int argc,char *argv[])
{
    SomeObject *so = NULL;
    DBusGConnection *bus;
    GMainLoop *mainLoop = NULL;
    unsigned int request_ret;
    GError *error = NULL;
 
    DBusGProxy *proxy = NULL;
    char *x;
    
    g_type_init();
 
    so = g_object_new(SOME_OBJECT_TYPE,NULL);
 
    bus = dbus_g_bus_get(DBUS_BUS_SESSION,NULL);
 
    proxy =
 dbus_g_proxy_new_for_name(bus,DBUS_SERVICE_DBUS,DBUS_PATH_DBUS,DBUS_INTERFACE_DBUS);
 
 
  dbus_g_connection_register_g_object(bus,"/com/example/SomeObject",G_OBJECT(so));
 
 
  if(!org_freedesktop_DBus_request_name(proxy,"com.example.SomeObject",0,&request_ret,&error))
    {
        g_print("Unable to register service/n");
        return 1;
    }
 
    mainLoop = g_main_loop_new(NULL,FALSE);
   g_main_loop_run(mainLoop);
    
    return 0;
}
 
 
 
DBus是一种用于进程间通信的协议,而DT7是一种用于传输车辆诊断信息的协议。要使用DBus协议进行DT7数据解码,需要以下步骤: 1. 安装DBus库和相关工具 在Linux系统中,可以使用以下命令安装DBus库和相关工具: ``` sudo apt-get install libdbus-1-dev dbus-x11 ``` 2. 创建DBus服务接口 可以使用DBus内置工具dbus-binding-tool来创建DBus服务接口。首先需要创建一个XML文件,定义DBus服务的接口和方法。例如,以下是一个简单的DBus服务接口定义文件,用于解码DT7数据: ``` <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node> <interface name="com.example.DT7Decoder"> <method name="decode"> <arg type="s" direction="in"/> <arg type="a{sv}" direction="out"/> </method> </interface> </node> ``` 以上定义了一个名为com.example.DT7Decoder的DBus服务接口,定义了一个名为decode的方法,该方法输入一个字符串类型的数据,输出一个键值对类型的数据。具体的方法实现需要在后续步骤中完成。 3. 使用dbus-binding-tool生成DBus服务代码 使用以下命令生成DBus服务代码: ``` dbus-binding-tool --mode=glib-server --prefix=dt7decoder --output=dt7decoder-generated --xml-file=dt7decoder.xml ``` 其中,--mode=glib-server表示生成基于GLib库的DBus服务代码,--prefix=dt7decoder表示生成的代码中的类名前缀为dt7decoder,--output=dt7decoder-generated表示生成的代码文件名为dt7decoder-generated.c和dt7decoder-generated.h,--xml-file=dt7decoder.xml表示使用dt7decoder.xml文件中的DBus服务接口定义。 4. 实现DBus服务接口方法 打开生成的dt7decoder-generated.c文件,在其中实现DBus服务接口的方法。例如,以下是一个简单的DT7数据解码方法实现: ``` static gboolean dt7decoder_decode (Dt7decoderDt7Decoder *object, gchar *data, GVariant **out_result, GError **error) { // 将传入的字符串类型数据解码为字节数组 gsize size = strlen(data); guint8 *bytes = g_malloc0(size / 2); for (gsize i = 0; i < size; i += 2) { gchar byte_str[3] = { data[i], data[i+1], '\0' }; bytes[i / 2] = (guint8)strtol(byte_str, NULL, 16); } // 对字节数组进行DT7数据解析 // ... // 将解析结果转换为键值对类型的数据返回 GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); g_variant_builder_add(&builder, "{sv}", "result", g_variant_new_string("OK")); *out_result = g_variant_builder_end(&builder); return TRUE; } ``` 以上代码中,dt7decoder_decode方法将传入的字符串类型数据解码为字节数组,进行DT7数据解析并返回解析结果。解析结果以键值对类型的数据形式返回。 5. 注册DBus服务 在程序启动时,需要将DBus服务注册到DBus总线中,以便其他进程可以通过DBus协议调用该服务。以下是一个简单的DBus服务注册代码: ``` DBusError error; dbus_error_init(&error); DBusConnection *connection = dbus_bus_get(DBUS_BUS_SESSION, &error); if (dbus_error_is_set(&error)) { fprintf(stderr, "DBus connection error: %s\n", error.message); dbus_error_free(&error); exit(1); } guint owner_id = 0; owner_id = dbus_connection_register_object(connection, "/com/example/DT7Decoder", dt7decoder_dt7_decoder_get_type(), &dt7decoder_vtable, NULL, &error); if (dbus_error_is_set(&error)) { fprintf(stderr, "DBus register object error: %s\n", error.message); dbus_error_free(&error); exit(1); } ``` 以上代码中,注册了一个名为com.example.DT7Decoder的DBus服务,DBus服务的对象路径为/com/example/DT7Decoder,DBus服务的类型为dt7decoder_dt7_decoder_get_type(),DBus服务的方法实现由dt7decoder_vtable提供。 6. 调用DBus服务 在其他进程中,可以使用DBus协议调用已注册的DBus服务。以下是一个简单的DBus服务调用代码: ``` DBusError error; dbus_error_init(&error); DBusConnection *connection = dbus_bus_get(DBUS_BUS_SESSION, &error); if (dbus_error_is_set(&error)) { fprintf(stderr, "DBus connection error: %s\n", error.message); dbus_error_free(&error); exit(1); } DBusMessage *message = dbus_message_new_method_call("com.example.DT7Decoder", "/com/example/DT7Decoder", "com.example.DT7Decoder", "decode"); if (!message) { fprintf(stderr, "DBus message creation error\n"); exit(1); } GVariant *data = g_variant_new_string("0123456789ABCDEF"); dbus_message_append_args(message, DBUS_TYPE_STRING, &data, DBUS_TYPE_INVALID); DBusMessage *reply = dbus_connection_send_with_reply_and_block(connection, message, -1, &error); if (dbus_error_is_set(&error)) { fprintf(stderr, "DBus method call error: %s\n", error.message); dbus_error_free(&error); exit(1); } GVariant *result; if (!dbus_message_get_args(reply, &error, DBUS_TYPE_ARRAY, DBUS_TYPE_DICT_ENTRY, &result, DBUS_TYPE_INVALID)) { fprintf(stderr, "DBus message reply error: %s\n", error.message); dbus_error_free(&error); exit(1); } // 处理解码结果 // ... dbus_message_unref(message); dbus_message_unref(reply); ``` 以上代码中,调用了名为com.example.DT7Decoder的DBus服务的decode方法,传入了一个字符串类型的数据。DBus服务返回了一个键值对类型的数据,包含了解码结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值