[Kde-bindings] Implementing Ruby DCOP
Richard Dale
Richard_Dale at tipitina.demon.co.uk
Thu Sep 25 14:00:32 UTC 2003
Ian Reinhart Geiser mentioned Ruby dcop on the kdecore list yesterday..
So I've been looking at how DCOP works, to see what needs to be done to make
it work with KDE ruby. In C++ you make your dcop class a sub-class of
DCOPObject, and add the K_DCOP macro in a similar manner to Q_OBJECt, and the
methods after the 'k_dcop:' label can be called from outside the app.
class AddresseeHelper : public QObject, public DCOPObject
{
K_DCOP
public:
static AddresseeHelper *self();
...
k_dcop:
ASYNC initSettings();
In Ruby I think it should look like this:
class AddresseeHelper < Qt::Object
def AddresseeHelper.self()
end
...
k_dcop 'ASYNC initSettings()'
def initSettings()
.. do stuff
end
The k_dcop contains a list of dcop slots, just like the current 'signals' and
'slots' declarations in QtRuby. AddressHelper doesn't need to be a subclass
of DCOPObject. When a new instance of AddressHelper is created, a associated
RubyDCOPProxy C++ instance would be instanciated, with the ruby VALUE of the
AddressHolder instance held as an instance variable. It would implement
process(), functions() and interfaces() methods derived from the strings in
the ruby 'k_dcop' statement.
The method is invoked in the process() virtual method overriden from
DCOPObject, for example:
bool UIServer::process(const QCString &fun, const QByteArray &data, QCString&
replyType, QByteArray &replyData)
{
static QAsciiDict<int>* fdict = 0;
if ( !fdict ) {
fdict = new QAsciiDict<int>( UIServer_fhash, true, false );
for ( int i = 0; UIServer_ftable[i][1]; i++ )
fdict->insert( UIServer_ftable[i][1], new int( i ) );
}
int* fp = fdict->find( fun );
switch ( fp?*fp:-1) {
case 0: { // int newJob(QCString,bool)
QCString arg0;
bool arg1;
QDataStream arg( data, IO_ReadOnly );
arg >> arg0;
arg >> arg1;
replyType = UIServer_ftable[0][0];
QDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << newJob(arg0, arg1 );
Here the two args needed for the newJob(QCString,bool) call are extracted into
arg0 and arg1 from the QDataStream 'data'. Then the method is called and the
int return value is serialized into the _replyStream QDataStream.
In ruby I originally thought it would mean adding two extra actions to the
marshalling 'VALUEtoDCOP', 'VALUEfromDCOP' or similar, in order to convert
ruby values to a QDataStream and back.
But the '<<' and '>>' methods are already in the Smoke runtime, so I think the
best way is to go through each argument type string in the dcop method
'QCString' and 'bool' above and call the appropriate '>>' method found via
findMethod() from the Smoke runtime. Each argument value returned by '>>'
would go into a ruby list, and the method 'newJob' called with the list.
VALUE argArray = rb_ary_new();
# Get each arg as a ruby value, and add to argArray.
...
rb_apply(self, rb_str_new2("newJob"), 2, argArray);
I think the api is already complete enough to invoke ruby signals, the args to
be emitted have to be copied into a QDataStream before the signal is emitted:
QByteArray params;
QDataStream stream(params, IO_WriteOnly);
stream << pid;
kapp->dcopClient()->emitDCOPSignal("clientDied(pid_t)", params);
That looks as though it should almost work in ruby to me.
params = ""
stream = Qt::DataStream.new(params, IO_WriteOnly)
stream << pid
$kapp.dcopClient().emitDCOPSignal("clientDied(pid_t)", params)
That doesn't look as friendly as:
$kapp.dcopClient().emitDCOPSignal( clientDied(pid) )
Which is more like emitting an ordinary signal. It needs more thought..
-- Richard
More information about the Kde-bindings
mailing list