Extended introspection

Thorvald Natvig thorvald at natvig.com
Tue Jun 17 09:01:04 PDT 2008


Thiago Macieira wrote:
> On Tuesday 17 June 2008 14:07:59 Thorvald Natvig wrote:
>   
>> Some of the DBus bindings (Java, C#, possibly more) require you to
>> manually type up an interface definition in that language matching the
>> interface to be used. I've been toying with the idea of writing a
>> xml-to-stub generator like that which is used for ICE, Thrift, CORBA
>> etc, but I run into a problem with structs. Take this snippet:
>> <arg name="players" type="a(isss)" direction="out"/>
>> We know the parameter is called "players", and it returns an array. But
>> what type is the array element? 'struct playersStruct { int i1; char
>> *string1}' etc doesn't really work, and forcing the user to define the
>> interface on his own means the struct members have different names in
>> the different languages. While adding enums, typedefs etc would be nice,
>> it's complete overkill and ruins the simple nature of the introspection
>> XML. But without the struct definitions, it's impossible to define the
>> interfaces in quite a few of the supported languages. Are there any
>> plans to address this?
>>     
>
> The way I dealt with this issue in QtDBus was to require an annotation 
> specifying which type the argument is, if it's not one of the basic types 
> (basic types are the one-letter types, plus "as" [QStringList] and "ay" 
> [QByteArray]).
>
> So, for an argument of type a(isss), it'll require you to declare to 
> qdbusxml2cpp that it's something like QList<Players> or 
> std::list<playersStruct> or PlayersArray, etc. The code generator doesn't 
> care about the memory layout or structure of the data. All it needs is the 
> type name to generate the code. With the proper #include in place, some 
> template magic will resolve the functions for marshalling and demarshalling.
>
>   

Well, I actually use the Qt bindings, so the full definition is:

<method name="getRegisteredPlayers">
      <arg name="filter" type="s" direction="in"/>
      <arg name="players" type="a(isss)" direction="out"/>
      <annotation name="com.trolltech.QtDBus.QtTypeName.Out1" 
value="QList&lt;RegisteredPlayer&gt;"/>
    </method>

Since the interface is extracted from Qt, Qt has no problems with this 
datatype. The problem is finding a way to bring this information (c++):
struct RegisteredPlayer {
        int id;
        QString name;
        QString email;
        QString pw;
        RegisteredPlayer();
};
into the other languages. For the perl bindings, the above just becomes 
an array with 4 elements of varying types. While it works, I'd like to 
type $player->name instead of $player[1]. But the introspection data 
doesn't carry the name of the individual parts of the struct, so that 
can't happen. The real problem comes along when someone wants to use 
this from C# or Java: The user will have to type up the interfaces on 
their own, and if they base that on the introspection data, we might end 
up with (c#):
public struct RegisteredPlayer {
    public int player_id;
    public string username;
    public string email;
    public string password;
}
which is functionally the same, except things switched names. 
Furthermore, the manual typing of the interfaces mean we're in trouble 
if we ever change the interface, and it also makes it very hard to 
document it. Effectively, to keep things synchronized, we will have to 
release pre-typed stub code for all those bindings, with this additional 
information added.

It just seems odd that we can name the functions and the parameters, but 
not struct members. If I redefine the above into:
<method name="getRegisteredPlayers">
      <arg name="filter" type="s" direction="in"/>
      <arg name="ids" type="ai" direction="out"/>
      <arg name="names" type="as" direction="out"/>
      <arg name="emails" type="as" direction="out"/>
     ...

then the function of each piece of data becomes clear, but the function 
call becomes ugly.



More information about the dbus mailing list