* Nested objects introspection patch (David Belser)

* More indentation in generated code (David Belser)
* Avoid redundant calls to dbus_bus_add_match (David Belser)
* Typo in HAVE_PTHREAD_H macro  (Olivier Hochreutiner)
* Allow other listeners to receive the same signal, if any (Olivier Hochreutiner)
This commit is contained in:
admin 2008-01-06 01:58:28 +01:00
parent ecd2428049
commit 68a722e6d1
10 changed files with 89 additions and 64 deletions

50
INSTALL
View file

@ -1,8 +1,8 @@
Installation Instructions Installation Instructions
************************* *************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
Software Foundation, Inc. 2006 Free Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it. unlimited permission to copy, distribute and modify it.
@ -10,7 +10,10 @@ unlimited permission to copy, distribute and modify it.
Basic Installation Basic Installation
================== ==================
These are generic installation instructions. Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package.
The `configure' shell script attempts to guess correct values for The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses various system-dependent variables used during compilation. It uses
@ -23,9 +26,9 @@ debugging `configure').
It can also use an optional file (typically called `config.cache' It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale disabled by default to prevent problems with accidental use of stale
cache files.) cache files.
If you need to do unusual things to compile the package, please try If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail to figure out how `configure' could check whether to do them, and mail
@ -35,20 +38,17 @@ some point `config.cache' contains results you don't want to keep, you
may remove or edit it. may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need `configure' by a program called `autoconf'. You need `configure.ac' if
`configure.ac' if you want to change it or regenerate `configure' using you want to change it or regenerate `configure' using a newer version
a newer version of `autoconf'. of `autoconf'.
The simplest way to compile this package is: The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type 1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're `./configure' to configure the package for your system.
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some Running `configure' might take a while. While running, it prints
messages telling which features it is checking for. some messages telling which features it is checking for.
2. Type `make' to compile the package. 2. Type `make' to compile the package.
@ -78,7 +78,7 @@ details on some of the pertinent environment variables.
by setting variables in the command line or in the environment. Here by setting variables in the command line or in the environment. Here
is an example: is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details. *Note Defining Variables::, for more details.
@ -87,17 +87,15 @@ Compiling For Multiple Architectures
You can compile the package for more than one kind of computer at the You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that own directory. To do this, you can use GNU `make'. `cd' to the
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH' With a non-GNU `make', it is safer to compile the package for one
variable, you have to compile the package for one architecture at a architecture at a time in the source code directory. After you have
time in the source code directory. After you have installed the installed the package for one architecture, use `make distclean' before
package for one architecture, use `make distclean' before reconfiguring reconfiguring for another architecture.
for another architecture.
Installation Names Installation Names
================== ==================
@ -190,12 +188,12 @@ them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc ./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script). Here is a another example: overridden in the site shell script).
/bin/bash ./configure CONFIG_SHELL=/bin/bash Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
configuration-related scripts to be executed by `/bin/bash'.
`configure' Invocation `configure' Invocation
====================== ======================

View file

@ -1,6 +1,6 @@
EXTRA_DIST = README echo-introspect.xml EXTRA_DIST = README echo-introspect.xml
AM_CPPFLAGS = -I$(top_srcdir)/include AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
noinst_PROGRAMS = echo-server noinst_PROGRAMS = echo-server

View file

@ -29,7 +29,7 @@
#include "config.h" #include "config.h"
#endif #endif
#ifdef HAVE_PTHREAD #ifdef HAVE_PTHREAD_H
#include <pthread.h> #include <pthread.h>
#endif #endif
@ -143,9 +143,9 @@ public:
private: private:
#if defined HAVE_PTHREAD #if defined HAVE_PTHREAD_H
pthread_mutex _mutex; pthread_mutex_t _mutex;
#elif defined HAVE_WIN32 #elif defined HAVE_WIN32

View file

@ -32,7 +32,7 @@
#include <glib.h> #include <glib.h>
#include "api.h" #include "api.h"
#include "eventloop.h" #include "dispatcher.h"
namespace DBus { namespace DBus {

View file

@ -104,6 +104,7 @@ public:
class ObjectAdaptor; class ObjectAdaptor;
typedef std::list<ObjectAdaptor*> ObjectAdaptorPList; typedef std::list<ObjectAdaptor*> ObjectAdaptorPList;
typedef std::list<std::string> ObjectPathList;
class DXXAPI ObjectAdaptor : public Object, public virtual AdaptorBase class DXXAPI ObjectAdaptor : public Object, public virtual AdaptorBase
{ {
@ -113,6 +114,8 @@ public:
static ObjectAdaptorPList from_path_prefix( const std::string& prefix ); static ObjectAdaptorPList from_path_prefix( const std::string& prefix );
static ObjectPathList child_nodes_from_prefix( const std::string& prefix );
struct Private; struct Private;
ObjectAdaptor( Connection& conn, const Path& path ); ObjectAdaptor( Connection& conn, const Path& path );

View file

@ -8,9 +8,11 @@ GLIB_H = $(HEADER_DIR)/glib-integration.h
GLIB_CPP = glib-integration.cpp GLIB_CPP = glib-integration.cpp
endif endif
CONFIG_H = $(top_builddir)/include/dbus-c++/config.h
HEADER_DIR = $(top_srcdir)/include/dbus-c++ HEADER_DIR = $(top_srcdir)/include/dbus-c++
HEADER_FILES = \ HEADER_FILES = \
$(HEADER_DIR)/config.h \ $(CONFIG_H) \
$(HEADER_DIR)/dbus.h \ $(HEADER_DIR)/dbus.h \
$(HEADER_DIR)/types.h \ $(HEADER_DIR)/types.h \
$(HEADER_DIR)/connection.h \ $(HEADER_DIR)/connection.h \

View file

@ -74,7 +74,7 @@ DefaultWatch::~DefaultWatch()
DefaultMutex::DefaultMutex() DefaultMutex::DefaultMutex()
{ {
#if defined HAVE_PTHREAD #if defined HAVE_PTHREAD_H
pthread_mutex_init(&_mutex, NULL); pthread_mutex_init(&_mutex, NULL);
@ -84,7 +84,7 @@ DefaultMutex::DefaultMutex()
DefaultMutex::~DefaultMutex() DefaultMutex::~DefaultMutex()
{ {
#if defined HAVE_PTHREAD #if defined HAVE_PTHREAD_H
pthread_mutex_destroy(&_mutex); pthread_mutex_destroy(&_mutex);
@ -94,7 +94,7 @@ DefaultMutex::~DefaultMutex()
void DefaultMutex::lock() void DefaultMutex::lock()
{ {
#if defined HAVE_PTHREAD #if defined HAVE_PTHREAD_H
pthread_mutex_lock(&_mutex); pthread_mutex_lock(&_mutex);
@ -104,7 +104,7 @@ void DefaultMutex::lock()
void DefaultMutex::unlock() void DefaultMutex::unlock()
{ {
#if defined HAVE_PTHREAD #if defined HAVE_PTHREAD_H
pthread_mutex_unlock(&_mutex); pthread_mutex_unlock(&_mutex);

View file

@ -131,7 +131,11 @@ bool InterfaceProxy::dispatch_signal( const SignalMessage& msg )
if( si != _signals.end() ) if( si != _signals.end() )
{ {
si->second.call( msg ); si->second.call( msg );
return true; // Here we always return false because there might be
// another InterfaceProxy listening for the same signal.
// This way we instruct libdbus-1 to go on dispatching
// the signal.
return false;
} }
else else
{ {

View file

@ -61,7 +61,7 @@ Message IntrospectableAdaptor::Introspect( const CallMessage& call )
IntrospectedInterface* const intro = iti->second->introspect(); IntrospectedInterface* const intro = iti->second->introspect();
if(intro) if(intro)
{ {
xml << "<interface name=\"" << intro->name << "\">"; xml << "\n\t<interface name=\"" << intro->name << "\">";
for(const IntrospectedProperty* p = intro->properties; p->name; ++p) for(const IntrospectedProperty* p = intro->properties; p->name; ++p)
{ {
@ -70,18 +70,18 @@ Message IntrospectableAdaptor::Introspect( const CallMessage& call )
if(p->read) access += "read"; if(p->read) access += "read";
if(p->write) access += "write"; if(p->write) access += "write";
xml << "<property name=\"" << p->name << "\"" xml << "\n\t\t<property name=\"" << p->name << "\""
<< " type=\"" << p->type << "\"" << " type=\"" << p->type << "\""
<< " access=\"" << access << "\"/>"; << " access=\"" << access << "\"/>";
} }
for(const IntrospectedMethod* m = intro->methods; m->args; ++m) for(const IntrospectedMethod* m = intro->methods; m->args; ++m)
{ {
xml << "<method name=\"" << m->name << "\">"; xml << "\n\t\t<method name=\"" << m->name << "\">";
for(const IntrospectedArgument* a = m->args; a->type; ++a) for(const IntrospectedArgument* a = m->args; a->type; ++a)
{ {
xml << "<arg direction=\"" << (a->in ? "in" : "out") << "\"" xml << "\n\t\t\t<arg direction=\"" << (a->in ? "in" : "out") << "\""
<< " type=\"" << a->type << "\""; << " type=\"" << a->type << "\"";
if(a->name) xml << " name=\"" << a->name << "\""; if(a->name) xml << " name=\"" << a->name << "\"";
@ -89,12 +89,12 @@ Message IntrospectableAdaptor::Introspect( const CallMessage& call )
xml << "/>"; xml << "/>";
} }
xml << "</method>"; xml << "\n\t\t</method>";
} }
for(const IntrospectedMethod* m = intro->signals; m->args; ++m) for(const IntrospectedMethod* m = intro->signals; m->args; ++m)
{ {
xml << "<signal name=\"" << m->name << "\">"; xml << "\n\t\t<signal name=\"" << m->name << "\">";
for(const IntrospectedArgument* a = m->args; a->type; ++a) for(const IntrospectedArgument* a = m->args; a->type; ++a)
{ {
@ -104,12 +104,22 @@ Message IntrospectableAdaptor::Introspect( const CallMessage& call )
xml << "/>"; xml << "/>";
} }
xml << "</signal>"; xml << "\n\t\t</signal>";
} }
xml << "</interface>"; xml << "\n\t</interface>";
} }
} }
const ObjectPathList nodes = ObjectAdaptor::child_nodes_from_prefix(path + '/');
ObjectPathList::const_iterator oni;
for(oni = nodes.begin(); oni != nodes.end(); ++oni)
{
xml << "\n\t<node name=\"" << (*oni) << "\"/>";
}
/* broken
const ObjectAdaptorPList children = ObjectAdaptor::from_path_prefix(path + '/'); const ObjectAdaptorPList children = ObjectAdaptor::from_path_prefix(path + '/');
ObjectAdaptorPList::const_iterator oci; ObjectAdaptorPList::const_iterator oci;
@ -121,8 +131,9 @@ Message IntrospectableAdaptor::Introspect( const CallMessage& call )
xml << "<node name=\"" << name << "\"/>"; xml << "<node name=\"" << name << "\"/>";
} }
*/
xml << "</node>"; xml << "\n</node>";
ReturnMessage reply(call); ReturnMessage reply(call);
MessageIter wi = reply.writer(); MessageIter wi = reply.writer();

View file

@ -119,6 +119,31 @@ ObjectAdaptorPList ObjectAdaptor::from_path_prefix( const std::string& prefix )
return ali; return ali;
} }
ObjectPathList ObjectAdaptor::child_nodes_from_prefix( const std::string& prefix )
{
ObjectPathList ali;
ObjectAdaptorTable::iterator ati = _adaptor_table.begin();
size_t plen = prefix.length();
while(ati != _adaptor_table.end())
{
if(!strncmp(ati->second->path().c_str(), prefix.c_str(), plen))
{
std::string p = ati->second->path().substr(plen);
p = p.substr(0,p.find('/'));
ali.push_back(p);
}
++ati;
}
ali.sort();
ali.unique();
return ali;
}
ObjectAdaptor::ObjectAdaptor( Connection& conn, const Path& path ) ObjectAdaptor::ObjectAdaptor( Connection& conn, const Path& path )
: Object(conn, path, conn.unique_name()) : Object(conn, path, conn.unique_name())
{ {
@ -138,16 +163,6 @@ void ObjectAdaptor::register_obj()
{ {
throw ErrorNoMemory("unable to register object path"); throw ErrorNoMemory("unable to register object path");
} }
else
{
InterfaceAdaptorTable::const_iterator ii = _interfaces.begin();
while( ii != _interfaces.end() )
{
std::string im = "type='method_call',interface='"+ii->first+"',path='"+path()+"'";
conn().add_match(im.c_str());
++ii;
}
}
_adaptor_table[path()] = this; _adaptor_table[path()] = this;
} }
@ -159,14 +174,6 @@ void ObjectAdaptor::unregister_obj()
debug_log("unregistering local object %s", path().c_str()); debug_log("unregistering local object %s", path().c_str());
dbus_connection_unregister_object_path(conn()._pvt->conn, path().c_str()); dbus_connection_unregister_object_path(conn()._pvt->conn, path().c_str());
InterfaceAdaptorTable::const_iterator ii = _interfaces.begin();
while( ii != _interfaces.end() )
{
std::string im = "type='method_call',interface='"+ii->first+"',path='"+path()+"'";
conn().remove_match(im.c_str());
++ii;
}
} }
void ObjectAdaptor::_emit_signal( SignalMessage& sig ) void ObjectAdaptor::_emit_signal( SignalMessage& sig )