2003-09-24 Seth Nickell <seth@gnome.org>
authorSeth Nickell <seth@gnome.org>
Thu, 25 Sep 2003 06:57:01 +0000 (06:57 +0000)
committerSeth Nickell <seth@gnome.org>
Thu, 25 Sep 2003 06:57:01 +0000 (06:57 +0000)
* python/dbus.py:

Connect Object methods (when you are sharing an object) up... pass
in a list of methods to be shared. Sharing all the methods just
worked out too weird. You can now create nice Services over the
DBus in Python. :-)

* python/dbus_bindings.pyx.in:

Keep references to user_data tuples passed into C functions so
Python doesn't garbage collect on us.

Implement MethodReturn and Error subclasses of Message for creating
DBusMessage's of those types.

* python/examples/example-client.py:
* python/examples/example-service.py:

Simple example code showing both how create DBus services and objects,
and how to use them.

ChangeLog
python/dbus.py
python/dbus_bindings.pyx.in
python/examples/example-client.py [new file with mode: 0644]
python/examples/example-service.py [new file with mode: 0644]

index 76fa41d..17b4fd4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2003-09-24  Seth Nickell  <seth@gnome.org>
+
+       * python/dbus.py:
+
+       Connect Object methods (when you are sharing an object) up... pass
+       in a list of methods to be shared. Sharing all the methods just
+       worked out too weird. You can now create nice Services over the
+       DBus in Python. :-)
+       
+       * python/dbus_bindings.pyx.in:
+
+       Keep references to user_data tuples passed into C functions so 
+       Python doesn't garbage collect on us.
+
+       Implement MethodReturn and Error subclasses of Message for creating
+       DBusMessage's of those types.
+       
+       * python/examples/example-client.py:
+       * python/examples/example-service.py:
+
+       Simple example code showing both how create DBus services and objects,
+       and how to use them.
+
 2003-09-23  Havoc Pennington  <hp@pobox.com>
 
        * glib/dbus-gproxy.c (dbus_gproxy_manager_filter): implement
index a7cca56..55e5944 100644 (file)
@@ -159,18 +159,35 @@ class Object:
     def __init__(self, object_path, methods_to_share, service):
         self._object_path = object_path
         self._service = service
-        self._object_methods = methods_to_share
         self._bus = service.get_bus()
         self._connection = self._bus.get_connection()
+
+        self._method_name_to_method = self._build_method_dictionary(methods_to_share)
         
         self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb)
 
     def _unregister_cb(self, connection):
         print ("Unregister")
         
-    def message_cb(self, connection, message):
-        print ("Message %s received" % (message))
-        print ("MethodCall %s" % (message.get_member()))
+    def _message_cb(self, connection, message):
+        target_method_name = message.get_member()
+        target_method = self._method_name_to_method[target_method_name]
+        args = message.get_args_list()
+        
+        retval = target_method(*args)
+
+        reply = dbus_bindings.MethodReturn(message)
+        if retval != None:
+            reply.append(retval)
+        self._connection.send(reply)
+
+    def _build_method_dictionary(self, methods):
+        dictionary = {}
+        for method in methods:
+            if dictionionary.has_key(method.__name__):
+                print ('WARNING: registering DBus Object methods, already have a method named %s' % (method.__name__)
+            dictionary[method.__name__] = method
+        return dictionary
         
 class RemoteService:
     """A remote service providing objects.
index 2e575ed..085a73f 100644 (file)
@@ -53,6 +53,8 @@ ctypedef struct DBusObjectPathVTable:
   void (* dbus_internal_pad4) (void *)
 
 
+_user_data_references = [ ]
+
 class DBusException(Exception):
     pass
 
@@ -72,6 +74,7 @@ cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection,
                                                   void *user_data):
     print ("cmessage_function_handler() called")
     tup = <object>user_data
+    print (type(tup))
     print (tup)
     function = tup[1]
     message = Message(_create=0)
@@ -102,7 +105,7 @@ cdef class Connection:
     # FIXME: this is a major major hack. We use this because casting values to
     # python objects and returning seemed to be corrupting them. This is a "global variable" :-(
     cdef char **_parsed_path
-    
+
     def __init__(self, address=None, _conn=None):
         cdef DBusError error
         dbus_error_init(&error)
@@ -301,7 +304,8 @@ cdef class Connection:
         cvtable.message_function    = cmessage_function_handler
 
         user_data = [unregister_cb, message_cb]
-        #Py_XINCREF(user_data)
+        global _user_data_references
+        _user_data_references.append(user_data)
         
         path_element_list = path[1:].split('/')
         self._build_parsed_path(path_element_list)
@@ -316,9 +320,8 @@ cdef class Connection:
         cvtable.message_function    = cmessage_function_handler
 
         user_data = [unregister_cb, message_cb]
-        Py_XINCREF(user_data)
-
-        print ("Ref inced")
+        global _user_data_references
+        _user_data_references.append(user_data)        
         
         path_element_list = path[1:].split('/')
         self._build_parsed_path(path_element_list)
@@ -586,8 +589,11 @@ cdef class MessageIter:
 cdef class Message:
     cdef DBusMessage *msg
 
-    def __init__(self, message_type=MESSAGE_TYPE_INVALID, service=None, path=None, interface=None,
-                 method=None, name=None, reply_to=None, error_name=None, error_message=None,
+    def __init__(self, message_type=MESSAGE_TYPE_INVALID,
+                 service=None, path=None, interface=None, method=None,
+                 method_call=None,
+                 name=None,
+                 reply_to=None, error_name=None, error_message=None,
                  _create=1):
         cdef char *cservice
         if (service == None):
@@ -596,18 +602,20 @@ cdef class Message:
             cservice = service
             
         if not _create:
-            return 0
+            return
 
         if message_type == MESSAGE_TYPE_METHOD_CALL:
             self.msg = dbus_message_new_method_call(cservice, path, interface, method)
         elif message_type == MESSAGE_TYPE_METHOD_RETURN:
-            msg = method_call._get_msg()
-            self.msg = dbus_message_new_method_return(<DBusMessage*>msg)
+            print ("Doing this")
+            cmsg = method_call._get_msg()
+            self.msg = dbus_message_new_method_return(<DBusMessage*>cmsg)
+            print ("Done")
         elif message_type == MESSAGE_TYPE_SIGNAL:
             self.msg = dbus_message_new_signal(path, interface, name)
         elif message_type == MESSAGE_TYPE_ERROR:
-            msg = reply_to._get_msg()
-            self.msg = dbus_message_new_error(<DBusMessage*>msg, error_name, error_message)
+            cmsg = reply_to._get_msg()
+            self.msg = dbus_message_new_error(<DBusMessage*>cmsg, error_name, error_message)
             
     def type_to_name(self, type):
         if type == MESSAGE_TYPE_SIGNAL:
@@ -797,6 +805,14 @@ class MethodCall(Message):
     def __init__(self, mpath, minterface, mmethod):
         Message.__init__(self, MESSAGE_TYPE_METHOD_CALL, path=mpath, interface=minterface, method=mmethod)
 
+class MethodReturn(Message):
+    def __init__(self, method_call):
+        Message.__init__(self, MESSAGE_TYPE_METHOD_RETURN, method_call=method_call)
+
+class Error(Message):
+    def __init__(self, reply_to, error_name, error_message):
+        Message.__init__(self, MESSAGE_TYPE_ERROR, reply_to=reply_to, error_name=error_name, error_message=error_message)
+        
 cdef class Server:
     cdef DBusServer *server
     def __init__(self, address):
diff --git a/python/examples/example-client.py b/python/examples/example-client.py
new file mode 100644 (file)
index 0000000..24906b8
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+
+import dbus
+
+bus = dbus.Bus()
+remote_service = bus.get_service("org.designfu.SampleService")
+remote_object = remote_service.get_object("/MyObject", "org.designfu.SampleInterface")
+
+remote_object.HelloWorld("Hello from example-client.py!")
diff --git a/python/examples/example-service.py b/python/examples/example-service.py
new file mode 100644 (file)
index 0000000..eb55af4
--- /dev/null
@@ -0,0 +1,16 @@
+import dbus
+
+import pygtk
+import gtk
+
+class MyObject(dbus.Object):
+    def __init__(self):
+        service = dbus.Service("org.designfu.SampleService")
+        dbus.Object("/MyObject", [self.HelloWorld], service)
+
+    def HelloWorld(self, arg1):
+        print ("Hello World!: %s" % (arg1))
+
+object = MyObject()
+
+gtk.main()