mvidner / ruby-dbus

A Ruby binding for DBus
GNU Lesser General Public License v2.1
170 stars 48 forks source link

service side: interface must be optional for methods if unambiguous #45

Open NTCoding opened 11 years ago

NTCoding commented 11 years ago

If I create the service from the example, I get the following on the command line

╰─➤ qdbus org.ruby.service /org/ruby/MyInstance signal void org.ruby.SampleInterface.SomethingJustHappened(QString toto, uint tutu) method void org.ruby.SampleInterface.hello(QString name, QString name2) method void org.ruby.SampleInterface.test_variant(QDBusVariant stuff) method QString org.ruby.AnotherInterface.Reverse(QString instr) method void org.ruby.AnotherInterface.ThatsALongMethodNameIThink()

Notice there is no introspect method. Also, I can't call any of the methods, I get the following error:

╰─➤ qdbus org.ruby.service /org/ruby/MyInstance Reverse "yay"
Error: org.freedesktop.DBus.Error.UnknownMethod Interface "" of object "/org/ruby/MyInstance" doesn't exist

I have created multiple service, in different applications, but still keep getting this error. When the method genuinely doesn't exist, there is another different error saying it cannot be found.

mvidner commented 11 years ago

Thanks for the report!

It is true that org.freedesktop.DBus.Introspectable.Introspect is missing from the qdbus output, but introspection does work, in fact qdbus uses it to get that output.

$ qdbus org.ruby.service /org/ruby/MyInstance org.freedesktop.DBus.Introspectable.Introspect
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.ruby.SampleInterface">
<method name="hello">
<arg name="name" direction="in" type="s"/>
<arg name="name2" direction="in" type="s"/>
</method>
<method name="test_variant">
<arg name="stuff" direction="in" type="v"/>
</method>
<signal name="SomethingJustHappened">
<arg name="toto" type="s"/>
<arg name="tutu" type="u"/>
</signal>
</interface>
<interface name="org.ruby.AnotherInterface">
<method name="ThatsALongMethodNameIThink">
</method>
<method name="Reverse">
<arg name="instr" direction="in" type="s"/>
<arg name="outstr" direction="out" type="s"/>
</method>
</interface>
</node>
mvidner commented 11 years ago

As the error message is trying to tell you (Interface "" of ... does not exist), ruby-dbus requires method names to be qualified with the interface name. So this works:

$ qdbus org.ruby.service /org/ruby/MyInstance org.ruby.AnotherInterface.Reverse gateman
nametag

Also, ruby-dbus as the caller is able to fill in the interface from the introspection data (see PR #35), but as I've just realized on rereading the specification, that's a wrong place to fix it since the service should handlle it:

A method call message is required to have a MEMBER header field indicating the name of the method. Optionally, the message has an INTERFACE field giving the interface the method is a part of. In the absence of an INTERFACE field, if two interfaces on the same object have a method with the same name, it is undefined which of the two methods will be invoked. Implementations may also choose to return an error in this ambiguous case. However, if a method name is unique implementations must not require an interface field.

So I will fix that.

mvidner commented 10 years ago

Funny thing, the newest release of the DBus specification (0.23 from yesterday) no longer requires that a missing interface works. It is discussed in bug#68597. But I'll fix it anyway.