D-Bus : Transmit a Data Array in Simple and Useful Form

本文通过一个具体的示例介绍了如何使用D-Bus进行字节数据数组的发送与接收。详细展示了客户端发送数据到服务器的过程,并解释了服务器端如何正确解析接收到的数据。特别注意了D-Bus中数据长度的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



     In lots situation, One would send data via a simple data structure :  a byte array contain real data, and a integer to note this data's length. This concept would appear when one uses the D-Bus, of Course.  For D-Bus, D-BUS_TYPE_ARRAY is different from the others data types, for it is not way to know the data length if there is no additional information. (length of DBUS_TYPE_STRING could be known by seeking where is the null flag.)

    In this example, I demonstrate How to send a data array via D-Bus.

   server.c :


 
/* server.c */

#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

DBusHandlerResult filter_func(DBusConnection *connection, 
      DBusMessage *message, void *usr_data)
{
    DBusMessage *reply;
    dbus_bool_t handled = false;
    char *pReadData;
    int len;
    unsigned char i;
     
    DBusError dberr;
    
    dbus_error_init(&dberr);
    
    printf("pReadData = %x\n", (unsigned int)pReadData);
    
    if(FALSE == dbus_message_get_args(message, &dberr, DBUS_TYPE_ARRAY,
  DBUS_TYPE_BYTE, &pReadData, &len,  DBUS_TYPE_INVALID) && 0 != len)
 {
  //printf("len = %d\n");
  //printf("receiver data error\n");
  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
 if(0 == len)
  return DBUS_HANDLER_RESULT_HANDLED;
    
    printf("len = %d, ", len);
    
    for( i = 0; i < len; i++)
  printf("%#2x ", (unsigned char)pReadData[i]);
 printf("\n");    
    handled = true;
    
    printf("pReadData = %x\n", (unsigned int)pReadData);
    
    /*if one free pReadData, it will crash!*/
    //dbus_free_string_array((char**)&pReadData);
    
    return (handled ? DBUS_HANDLER_RESULT_HANDLED :
  DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
  
}/*filter_func*/


int main(int argc, char *argv[])
{
    DBusError dberr;
    DBusConnection *dbconn;

    dbus_error_init(&dberr);
    dbconn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);

    if (!dbus_connection_add_filter(dbconn, filter_func, NULL, NULL)) {
        return -1;
    }

    dbus_bus_add_match(dbconn, "type='signal',interface='gaiger.Drstein.Demonstration'", &dberr);
    
    while(dbus_connection_read_write_dispatch(dbconn, -1)) {
        /* loop */
    }
    
    return 0;
}/*main*/


    Take a notice: the buffer which containers received data is allocated by D-Bus, you could not release it manually. D-Bus would manage this buffer automatically, it would not occur memory leaking.


client.c :


#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int db_send(DBusConnection *dbconn)
{
    DBusMessage *dbmsg;
    char *pSendData;
    int len;
    unsigned char i;

 pSendData = (char *)malloc(256);
 
    dbmsg = dbus_message_new_signal("/client/signal/Object", 
  "gaiger.Drstein.Demonstration", "Test");
  
 len = 6;
 for(i = 0; i < len; i++)
  pSendData[i] = (unsigned char)i;
   
    if (!dbus_message_append_args(dbmsg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
  &pSendData,  len, DBUS_TYPE_INVALID)) 
 {
  return -1;
    }

    if (!dbus_connection_send(dbconn, dbmsg, NULL)) {
        return -1;
    }
    
    dbus_connection_flush(dbconn);
    printf("send message : len = %d, ", len );
    
 for( i = 0; i < len; i++)
  printf("%#x ", (unsigned char)pSendData[i]);
    
 printf("\n"); 
    dbus_message_unref(dbmsg);    
    free(pSendData);
   
    return 0;
}/**/


int main(int argc, char *argv[])
{
 unsigned int i;
    DBusError dberr;
    DBusConnection *dbconn;

    dbus_error_init(&dberr);

    dbconn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);

#if(1)    
    for(i = 0; i < 3; i++)
  db_send(dbconn);
#else
    while(dbus_connection_read_write_dispatch(dbconn, -1)) {
        db_send(dbconn);
    }
#endif  
  
    dbus_connection_unref(dbconn);
    return 0;
}

    The two codes are consistent,  client could send data to server. Hope it is useful.

Note the line :


 if(FALSE == dbus_message_get_args(message, &dberr, DBUS_TYPE_ARRAY,
 DBUS_TYPE_BYTE, &pReadData, &len,  DBUS_TYPE_INVALID) && 0 != len)


    The type of the length variable should be int, even your data length is as long as int. It is, inside the Dbus library, the lengh pointer has been assume as int*. If you put the other integer types as length,  The values in vicinity of the passed length may be marred,  it would let to crash.

   More detail please ref this post in stack overflow.

If you do not know how to rewrite Makefile for the 2 codes, you could refer to this post I wrote.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值