From 6f5fc71b10ab910612b7af767308f52bb8266b1e Mon Sep 17 00:00:00 2001 From: Seth Nickell Date: Thu, 25 Sep 2003 06:57:01 +0000 Subject: [PATCH] 2003-09-24 Seth Nickell * 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 | 23 ++++++++++++++++++++++ python/dbus.py | 25 ++++++++++++++++++++---- python/dbus_bindings.pyx.in | 40 ++++++++++++++++++++++++++------------ python/examples/example-client.py | 9 +++++++++ python/examples/example-service.py | 16 +++++++++++++++ 5 files changed, 97 insertions(+), 16 deletions(-) create mode 100644 python/examples/example-client.py create mode 100644 python/examples/example-service.py diff --git a/ChangeLog b/ChangeLog index 76fa41d..17b4fd4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2003-09-24 Seth Nickell + + * 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 * glib/dbus-gproxy.c (dbus_gproxy_manager_filter): implement diff --git a/python/dbus.py b/python/dbus.py index a7cca56..55e5944 100644 --- a/python/dbus.py +++ b/python/dbus.py @@ -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. diff --git a/python/dbus_bindings.pyx.in b/python/dbus_bindings.pyx.in index 2e575ed..085a73f 100644 --- a/python/dbus_bindings.pyx.in +++ b/python/dbus_bindings.pyx.in @@ -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 = 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(msg) + print ("Doing this") + cmsg = method_call._get_msg() + self.msg = dbus_message_new_method_return(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(msg, error_name, error_message) + cmsg = reply_to._get_msg() + self.msg = dbus_message_new_error(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 index 0000000..24906b8 --- /dev/null +++ b/python/examples/example-client.py @@ -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 index 0000000..eb55af4 --- /dev/null +++ b/python/examples/example-service.py @@ -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() -- 2.7.4