Example of Producer: Use producer-glib

Source: Internet
Author: User
Tags touch command
Document directory
  • 5.1 code
  • 5.2 execution
  • 6.1. Configure. AC
  • 6.2. src/makefile. AM

 

4. complex data types

How does one process complex data types in a shard? The first suggestion is to try not to use complex data types. But what if they do? Some netizens suggest using garray as a container. Whatever the parameter, They manually put garray on the client side and retrieve it on the server side. This is indeed an idea and is suitable for self-developed servers and clients. Another article "How to pass a variant with your-glib" describes how to use gvalue to transmit complex data types. For more information, see.

The following describes how to process the {SV} parameter in our example:

$ cat sms_features.h#ifndef SMS_FEATURES_H#define SMS_FEATURES_H#include <glib-object.h>GHashTable *sms_create_features(const char * alphabet, int csm_num, int csm_seq);GType sms_get_features_type(void);void sms_release_features(GHashTable *features);void sms_show_features(GHashTable *features);#endif

Sms_features.h declares several functions. In this example, both the server and client call. The following are the implementations of these functions:

$ cat -n sms_features.c     1  #include "sms_features.h"     2     3  static void release_val(gpointer data)     4  {     5      GValue *val = (GValue *)data;     6      g_value_unset(val);     7      g_free(val);     8  }     9    10  GHashTable *sms_create_features(const char * alphabet, int csm_num, int csm_seq)    11  {    12      GHashTable *hash;    13      GValue *val;    14    15      hash = g_hash_table_new_full  (g_str_hash, NULL, NULL, release_val);    16    17      val = g_new0(GValue, 1);    18      g_value_init (val, G_TYPE_STRING);    19      g_value_set_string (val, alphabet);    20      g_hash_table_insert(hash, "alphabet", val);    21    22      val = g_new0(GValue, 1);    23      g_value_init (val, G_TYPE_INT);    24      g_value_set_int (val, csm_num);    25      g_hash_table_insert(hash, "csm_num", val);    26    27      val = g_new0(GValue, 1);    28      g_value_init (val, G_TYPE_INT);    29      g_value_set_int (val, csm_seq);    30      g_hash_table_insert(hash, "csm_seq", val);    31    32      return hash;    33  }    34    35  GType sms_get_features_type(void)    36  {    37      return dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);    38  }    39    40  void sms_show_features(GHashTable *features)    41  {    42      GList *keys = g_hash_table_get_keys(features);    43      gint len = g_list_length(keys);    44      gint i;    45    46      for (i = 0; i < len; i++) {    47          gchar  *key = g_list_nth_data(keys, i);    48          GValue *val = g_hash_table_lookup(features, key);    49    50          g_print("%s=", key);    51          switch (G_VALUE_TYPE(val)) {    52          case G_TYPE_STRING:    53              g_print("%s/n", g_value_get_string(val));    54              break;    55          case G_TYPE_INT:    56              g_print("%d/n", g_value_get_int(val));    57              break;    58          default:    59              g_print("Value is of unmanaged type!/n");    60          }    61      }    62    63      g_list_free(keys);    64  }    65    66  void sms_release_features(GHashTable *features)    67  {    68      g_hash_table_destroy(features);    69  }    70

Sms_get_features_type call dbus_g_type_get_map to create a {SV} type. The server is used to create signals. The client will use the call method and registration signal. Sms_create_features calls g_hash_table_new_full to create a hash table, and registers the clearing function of the value object at the same time. When sms_release_features calls g_hash_table_destroy to destroy the hash table, the value object cleanup function registered during creation is called.

5. Client 5.1, code

The client program is as follows:

$ cat -n smsc.c     1  #include <dbus/dbus-glib.h>     2  #include <stdio.h>     3  #include <stdlib.h>     4  #include <string.h>     5  #include <glib/giochannel.h>     6  #include "sms-marshal.h"     7  #include "sms_features.h"     8     9  #define SMSC_DEBUG    10    11  static void lose (const char *str, ...)    12  {    13      va_list args;    14      va_start (args, str);    15      vfprintf (stderr, str, args);    16      fputc ('/n', stderr);    17      va_end (args);    18      exit (1);    19  }    20    21  static void lose_gerror (const char *prefix, GError *error)    22  {    23      if (error) {    24          lose ("%s: %s", prefix, error->message);    25      }    26      else {    27          lose ("%s", prefix);    28      }    29  }    30    31  static void incoming_message_handler (DBusGProxy *proxy, const char *address, const char *contents, GHashTable *features, gpointer user_data)    32  {    33      printf ("Received message with addree /"%s/" and it says: /n%s/n", address, contents);    34      sms_show_features(features);    35  }    36    37  static void send_message(DBusGProxy *remote_object)    38  {    39      GError *error = NULL;    40      GHashTable *features;    41      int ret;    42    43      features = sms_create_features ("gsm", 8, 2);    44      printf("SendMessage ");    45    46      if (!dbus_g_proxy_call (remote_object, "SendMessage", &error,    47          G_TYPE_STRING, "10987654321", G_TYPE_STRING, "hello world",    48          sms_get_features_type(), features, G_TYPE_INVALID,    49          G_TYPE_INT, &ret, G_TYPE_INVALID))    50          lose_gerror ("Failed to complete SendMessage", error);    51    52      printf("return %d/n", ret);    53      sms_release_features(features);    54  }    55    56  static void shell_help(void)    57  {    58      printf( "/ts/tsend message/n"    59          "/tq/tQuit/n"    60          );    61  }    62    63  #define STDIN_BUF_SIZE    1024    64  static gboolean channel_cb(GIOChannel *source, GIOCondition condition, gpointer data)    65  {    66      int rc;    67      char buf[STDIN_BUF_SIZE+1];    68      DBusGProxy *remote_object = (DBusGProxy *)data;    69    70      if (condition != G_IO_IN) {    71          return TRUE;    72      }    73    74      /* we've received something on stdin.    */    75      printf("# ");    76      rc = fscanf(stdin, "%s", buf);    77      if (rc <= 0) {    78          printf("NULL/n");    79          return TRUE;    80      }    81    82      if (!strcmp(buf, "h")) {    83          shell_help();    84      } else if (!strcmp(buf, "?")) {    85          shell_help();    86      } else if (!strcmp(buf, "s")) {    87          send_message(remote_object);    88      } else if (!strcmp(buf, "q")) {    89          exit(0);    90      } else {    91          printf("Unknown command `%s'/n", buf);    92      }    93      return TRUE;    94  }    95    96  int main (int argc, char **argv)    97  {    98      DBusGConnection *bus;    99      DBusGProxy *remote_object;   100      GError *error = NULL;   101      GMainLoop *mainloop;   102      GIOChannel *chan;   103      guint source;   104      GType features_type;   105   106  #ifdef SMSC_DEBUG   107      g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, TRUE);   108  #endif   109      g_type_init ();   110      mainloop = g_main_loop_new (NULL, FALSE);   111   112      bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);   113      if (!bus)   114          lose_gerror ("Couldn't connect to session bus", error);   115   116      remote_object = dbus_g_proxy_new_for_name (bus, "org.freesmartphone.ogsmd",   117          "/org/freesmartphone/GSM/Device",   118          "org.freesmartphone.GSM.SMS");   119      if (!remote_object)   120          lose_gerror ("Failed to get name owner", NULL);   121   122      features_type = sms_get_features_type();   123      dbus_g_object_register_marshaller (sms_marshal_VOID__STRING_STRING_BOXED, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING,   124          features_type, G_TYPE_INVALID);   125      dbus_g_proxy_add_signal (remote_object, "IncomingMessage", G_TYPE_STRING, G_TYPE_STRING, features_type, G_TYPE_INVALID);   126      dbus_g_proxy_connect_signal (remote_object, "IncomingMessage", G_CALLBACK (incoming_message_handler), NULL, NULL);   127   128      chan = g_io_channel_unix_new(0);   129      source = g_io_add_watch(chan, G_IO_IN, channel_cb, remote_object);   130      g_main_loop_run (mainloop);   131      exit (0);   132  }

Line 3 connects to the session bus. Row 116-118 gets the connection on the session bus "org. freesmartphone. "org. freesmartphone. GSM. the interface proxy object of SMS.

Row 3 calls dbus_g_object_register_marshaller to register the column set function with feature-glib. Line 3 calls dbus_g_proxy_add_signal to add a listener for incomingmessage. The callback function of incomingmessage. Row 123 registers the sms_external_void _ string_string_boxed function generated using glib-genequalal. Callback-glib uses this function to retrieve signal parameters from the signal message and pass them to the callback function, that is, to execute the scattered set operation. This indicates that the column set function generated by glib-genstmal can be used for both the column set and the scattered set.

The client program also uses the IO channel to accept user input. When registering the callback function, Row 3 imports a pointer to the interface proxy object as a parameter. The callback function channel_cb calls the sendmessage method of the org. freesmartphone. GSM. SMS interface object through the send_message function after you type the 's' command. The g_slice_config_always_malloc setting in row 107 is also used to check memory leakage with valgrind.

5.2 execution

Run container-monitor first, then SMSs, and then SMSC. First, type 's' in SMSC and press enter to call the sendmessage method. Then, type 's' in SMSs and press enter to send the incomingmessage signal. Then, type 'q' in SMSC and press enter to exit. Finally, type 'q' in SMSs and press enter to exit.

$ ./smssservice is runningnumber=10987654321contents=hello worldcsm_num=8alphabet=gsmcsm_seq=2h#       s       send signal        q       Quits# q
$ ./smsch#       s       send message        q       Quits# SendMessage return 11Received message with addree "12345678901" and it says: hello signal!csm_num=3alphabet=ucs2csm_seq=1q

We can see the printed signal and message. For the same thing, the observer at different levels will see different details. The following table shows what the observer-monitor sees:

SMSs connects to the session bus. The session bus sends the nameownerchanged signal, and the unique Notification name ": 1.21" is allocated. Signal sender = org. freedesktop. Large-> DEST = (null destination) Path =/org/freedesktop/large; interface = org. freedesktop. Large; member = nameownerchanged
String ": 1.21"
String ""
String ": 1.21"
SMSs sends hello to the session bus to get its unique name ": 1.21 ". Method call sender =: 1.21-> DEST = org. freedesktop. Export Path =/org/freedesktop/export; interface = org. freedesktop. Submit; member = Hello
SMSs calls addmatch to receive the nameownerchanged signal of the session bus. Method call sender =: 1.21-> DEST = org. freedesktop. Export Path =/org/freedesktop/plugin; interface = org. freedesktop. plugin; member = addmatch
String "type = 'signal ', sender = 'org. freedesktop. export ', Path ='/org/freedesktop/export ', interface = 'org. freedesktop. comment ', member = 'nameownerchanged '"
SMSs calls addmatch to receive all signals sent by the session bus. Method call sender =: 1.21-> DEST = org. freedesktop. Export Path =/org/freedesktop/plugin; interface = org. freedesktop. plugin; member = addmatch
String "type = 'signal ', sender = 'org. freedesktop. login', Path ='/', interface = 'org. freedesktop. login '"
SMSs calls getnameowner to obtain the unique name of the Connection "org. freedesktop. connector. Method call sender =: 1.21-> DEST = org. freedesktop. Export Path =/org/freedesktop/partition; interface = org. freedesktop. Producer; member = getnameowner
String "org. freedesktop. Large"
The session bus sends the nameownerchanged signal, and the only connection with the name ": 1.21" is notified to get the public name "org. freesmartphone. ogsmd ". Signal sender = org. freedesktop. Large-> DEST = (null destination) Path =/org/freedesktop/large; interface = org. freedesktop. Large; member = nameownerchanged
String "org. freesmartphone. ogsmd"
String ""
String ": 1.21"
SMSs request public name "org. freesmartphone. ogsmd ". Before the public name allocation, the request for public name should be followed by the monitoring process reversing the message order. Method call sender =: 1.21-> DEST = org. freedesktop. Export Path =/; interface = org. freedesktop. Submit; member = requestname
String "org. freesmartphone. ogsmd"
Uint32 0
SMSC connects to the session bus. The session bus sends the nameownerchanged signal, and the unique Notification name ": 1.22" is allocated. Signal sender = org. freedesktop. Large-> DEST = (null destination) Path =/org/freedesktop/large; interface = org. freedesktop. Large; member = nameownerchanged
String ": 1.22"
String ""
String ": 1.22"
SMSs sends hello to the session bus to get its unique name ": 1.22 ". Method call sender =: 1.22-> DEST = org. freedesktop. Export Path =/org/freedesktop/export; interface = org. freedesktop. Submit; member = Hello
SMSC calls addmatch to receive the nameownerchanged signal of the session bus. Method call sender =: 1.22-> DEST = org. freedesktop. Export Path =/org/freedesktop/plugin; interface = org. freedesktop. plugin; member = addmatch
String "type = 'signal ', sender = 'org. freedesktop. export ', Path ='/org/freedesktop/export ', interface = 'org. freedesktop. comment ', member = 'nameownerchanged '"
SMSC calls addmatch to receive signals from the 'org. freesmartphone. ogsmd 'interface of the object'/org/freesmartphone/GSM/devic' in the 'org. freesmartphone. msms 'connection. Method call sender =: 1.22-> DEST = org. freedesktop. Export Path =/org/freedesktop/plugin; interface = org. freedesktop. plugin; member = addmatch
String "type = 'signal ', sender = 'org. freesmartphone. ogsmd ', Path ='/org/freesmartphone/GSM/devic', interface = 'org. freesmartphone. GSM. SMS '"
SMSC calls getnameowner to obtain the unique name of the Connection "org. freesmartphone. ogsmd. Method call sender =: 1.22-> DEST = org. freedesktop. Export Path =/org/freedesktop/partition; interface = org. freedesktop. Producer; member = getnameowner
String "org. freesmartphone. ogsmd"
SMSC calls the sendmessage method of the 'org. freesmartphone. message' interface of the object '/org/freesmartphone/GSM/devic' in the connection 'org. freesmartphone. ogsmd. Method call sender =: 1.22-> DEST = org. freesmartphone. ogsmd Path =/org/freesmartphone/GSM/device; interface = org. freesmartphone. GSM. SMS; member = sendmessage
String "10987654321"
String "Hello World"
Array [
Dict entry (
String "csm_seq"
Variant int32 2
)
Dict entry (
String "Alphabet"
Variant string "GSM"
)
Dict entry (
String "csm_num"
Variant int32 8
)
]
SMSs sends the method return message to SMSC and returns the output parameters of the sendmessage method. Method return sender =: 1.21-> DEST =: 1.22 reply_serial = 5
Int32 11
SMSs sends the incomingmessage signal. Signal sender =: 1.21-> DEST = (null destination) Path =/org/freesmartphone/GSM/device; interface = org. freesmartphone. GSM. SMS; member = incomingmessage
String "12345678901"
String "Hello signal! "
Array [
Dict entry (
String "csm_seq"
Variant int32 1
)
Dict entry (
String "Alphabet"
Variant string "ucs2"
)
Dict entry (
String "csm_num"
Variant int32 3
)
]
Session bus notification connection ": 1.22", that is, the SMSC connection has been disconnected. Signal sender = org. freedesktop. Large-> DEST = (null destination) Path =/org/freedesktop/large; interface = org. freedesktop. Large; member = nameownerchanged
String ": 1.22"
String ": 1.22"
String ""
The session bus notifies you that the connection with the public name "org. freesmartphone. ogsmd" has been disconnected. Signal sender = org. freedesktop. Large-> DEST = (null destination) Path =/org/freedesktop/large; interface = org. freedesktop. Large; member = nameownerchanged
String "org. freesmartphone. ogsmd"
String ": 1.21"
String ""
The connection with the unique name ": 1.21" of the session bus notification has been disconnected. That is, the SMSs has been terminated. Signal sender = org. freedesktop. Large-> DEST = (null destination) Path =/org/freedesktop/large; interface = org. freedesktop. Large; member = nameownerchanged
String ": 1.21"
String ": 1.21"
String ""
6. Engineering

The downloaded files are created using make distcheck, which contains automatically generated files. Execute./clean. Sh to delete the automatically generated files, leaving only the files I created:

$ find . -type f./clean.sh./Makefile.am./autogen.sh./src/gsm_sms.h./src/Makefile.am./src/sms-marshal.list./src/smss.xml./src/smss.c./src/gsm_sms.c./src/sms_features.h./src/sms_features.c./src/smsc.c./configure.ac

All source files have been described earlier. Let's take a look at the project file:

$ cat autogen.sh#! /bin/shtouch `find .`aclocalautoconfautoheadertouch NEWS README AUTHORS ChangeLogautomake --add-missing$ cat Makefile.amSUBDIRS = srcEXTRA_DIST = autogen.sh clean.sh

Autogen. Sh creates a project environment. After clean. Sh is executed, execute autogen. Sh to regenerate project files such as configure. The touch command is used to prevent the file from having a future timestamp. This type of problem may occur when I run Ubuntu on a virtual machine. Makefile. am also uses autogen. Sh clean. Sh as the release file. The most important project files are "Configure. ac" and "src/makefile. Am ".

6.1. Configure. AC
$ cat -n configure.ac     1  AC_INIT()     2  AM_INIT_AUTOMAKE(hello-dbus5, 0.1)     3  AM_CONFIG_HEADER(config.h)     4     5  AC_PROG_CC     6     7     8  # Dbus detection     9  PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.1, have_dbus=yes, have_dbus=no)    10    11  if test x$have_dbus = xno ; then    12      AC_MSG_ERROR([DBus development libraries not found])    13  fi    14  AM_CONDITIONAL(HAVE_DBUS, test x$have_dbus = xyes)    15    16  AC_SUBST(DBUS_CFLAGS)    17  AC_SUBST(DBUS_LIBS)    18    19    20  # Glib detection    21  PKG_CHECK_MODULES(DBUS_GLIB, gobject-2.0 >= 2.6, have_glib=yes, have_glib=no)    22    23  if test x$have_glib = xno ; then    24      AC_MSG_ERROR([GLib development libraries not found])    25  fi    26    27  AM_CONDITIONAL(HAVE_GLIB, test x$have_glib = xyes)    28    29  AC_SUBST(DBUS_GLIB_CFLAGS)    30  AC_SUBST(DBUS_GLIB_LIBS)    31    32    33  AC_OUTPUT([Makefile    34             src/Makefile])

Line 8-17 checks the inventory library, which will generate the compilation constants dbus_cflags and dbus_libs. Check the runtime-glib library in rows 20-30. They will generate the compilation constants dbus_glib_cflags and dbus_glib_libs.

6.2. src/makefile. AM
$ cat -n src/Makefile.am     1  INCLUDES = /     2          $(DBUS_CFLAGS)                          /     3          $(DBUS_GLIB_CFLAGS)                     /     4          -DDBUS_COMPILATION     5     6  LIBS = /     7          $(DBUS_LIBS)                            /     8          $(DBUS_GLIB_LIBS)                       /     9          -ldbus-glib-1    10    11  # smss    12  noinst_PROGRAMS = smss    13    14  BUILT_SOURCES = smss-glue.h sms-marshal.h sms-marshal.c    15  smss_SOURCES = $(BUILT_SOURCES) smss.c gsm_sms.c sms_features.c    16  noinst_HEADERS = gsm_sms.h sms_features.h    17    18    19  smss-glue.h: smss.xml    20          $(LIBTOOL) --mode=execute dbus-binding-tool --prefix=gsm_sms --mode=glib-server --output=smss-glue.h $(srcdir)/smss.xml    21    22  sms-marshal.h: sms-marshal.list    23          $(LIBTOOL) --mode=execute glib-genmarshal --header sms-marshal.list --prefix=sms_marshal > sms-marshal.h    24    25  sms-marshal.c: sms-marshal.list    26          $(LIBTOOL) --mode=execute glib-genmarshal --body sms-marshal.list --prefix=sms_marshal > sms-marshal.c    27    28  CLEANFILES = $(BUILT_SOURCES)    29    30  EXTRA_DIST = smss.xml sms-marshal.list    31    32  # smss    33  noinst_PROGRAMS += smsc    34  smsc_SOURCES= smsc.c sms-marshal.c sms_features.c

Line 19-20 The smss-glue.h of the stub file is generated by the interface description file SMSs. xml. 22-26 rows are defined by the column set interface to generate code containing the column set function.

7. Conclusion

This article describes a simple example of secure-glib, including servers and clients. In the first lecture, there is an addition example. If you understand the example in this article, the example is simpler. The producer-glib Source Code contains two examples:

  • Example-service and example-client demonstrate method call. In this example, the interface description file contains an error in parameter type. If (US) is written as (SS), an error occurs during running. The author may want to demonstrate the consequences of inconsistent interface definitions with code implementations. You can download the modified Code from here.
  • Example-signal-emitter and example-signal-recipient demonstrate signal transmission. In this example, example-signal-recipient calls the example-signal-emitter method to send signals. In fact, the signal should be from the server side. I changed it to typing in example-signal-emitter to send a signal. You can download the modified Code from here.

Now, let's see how to explain the renewal instance. In fact, all my articles only hope to make the complex world a little simpler.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.