[fpc-pascal] DBus interface needs an update
Luca Olivetti
luca at ventoso.org
Tue May 19 12:04:28 CEST 2009
En/na Jonathan ha escrit:
> On Mon, 18 May 2009 13:38:55 +0200
> Matthias Klumpp <matthias at nlinux.org> wrote:
>
>> I've spent hours to get the Pascal DBus interface working for me, but even
>> the example code does not work.
>
> I need to use DBus to but I can not make it work.
> Has anyone made DBus and HAL work with fpc?
About a year and a half ago I had DBus working, but I used it only to
communicate between my apps (so I have both a server and a client part).
Sorry, I cannot help too much, I just hope that whatever change is made
it doesn't break backwards compatibility.
Below is the client part (the usage of the reply parameters is specific
to my application, but the method should be general) inside a form.
ErrorDbus is a method that displays and logs the error message.
some private fields of the form:
//Dbus
err: DBusError;
conn: PDBusConnection;
in formCreate:
{ Initializes the errors }
dbus_error_init(@err);
{ Connection }
conn := dbus_bus_get(DBUS_BUS_SYSTEM, @err);
if dbus_error_is_set(@err) <> 0 then
begin
ErrorDbus('Connection Error: ' + err.message);
dbus_error_free(@err);
end;
cyclic bus call (called from a 200ms timer), note that I expect 14
parameters in the reply.
procedure TEstadoForm.BusCall;
const MAXPARAM=14;
var
msg: PDBusMessage;
args: DBusMessageIter;
pending: PDBusPendingCall;
param: PChar;
i:integer;
numparams:integer;
LocByte:byte;
LocString:string;
LocInteger:integer;
NoMoreParams:boolean;
procedure NextParam;
begin
if NoMoreParams then exit;
numparams:=numparams+1;
if dbus_message_iter_next(@args)=0 then
begin
if numparams<=MAXPARAM then ErrorDbus('Not enough parameters');
NoMoreParams:=true;
end;
end;
function GetStringParam:boolean;
begin
if NoMoreParams then
begin
result:=false;
exit;
end;
result:=dbus_message_iter_get_arg_type(@args)=DBUS_TYPE_STRING;
if not result then
begin
ErrorDbus(format('Parameter %d is not a string',[numparams]));
exit;
end;
dbus_message_iter_get_basic(@args, @param);
LocString:=strpas(param);
end;
function GetByteParam:boolean;
var partype:cint;
begin
if NoMoreParams then
begin
result:=false;
exit;
end;
partype:=dbus_message_iter_get_arg_type(@args);
result:=partype=DBUS_TYPE_BYTE;
if not result then
begin
//dirty trick: since the first response parameter should be
//a byte, here I check if it is a string
//in such case it is a dbus error message
if (numparams=1) and (partype=DBUS_TYPE_STRING) then
begin
dbus_message_iter_get_basic(@args, @param);
ErrorDbus(param);
numparams:=MAXPARAM;
exit;
end;
ErrorDbus(format('Parameter %d is not a byte',[numparams]));
exit;
end;
dbus_message_iter_get_basic(@args, @LocByte);
end;
function GetIntegerParam:boolean;
begin
result:=false;
if NoMoreParams then exit;
if dbus_message_iter_get_arg_type(@args)<>DBUS_TYPE_INT32 then
begin
ErrorDbus(format('Parameter %d is not int32',[numparams]));
exit;
end;
result:=true;
dbus_message_iter_get_basic(@args, @LocInteger);
end;
begin
ErrorDbus('ok');
// create a new method call and check for errors
msg := dbus_message_new_method_call('es.wetron.almacen_tapas.server',
// target for the method call
'/almacen_tapas/method/Object',
// object to call on
'es.wetron.almacen_tapas.method.Status', // interface to call on
'GetStatus'); // method name
if (msg = nil) then
begin
ErrorDbus('Message Null');
Exit;
end;
// send message and get a handle for a reply
if (dbus_connection_send_with_reply(conn, msg, @pending, -1) = 0)
then // -1 is default timeout
begin
ErrorDbus('Out Of Memory!');
Exit;
end;
if (pending = nil) then
begin
ErrorDbus('Pending Call Null');
Exit;
end;
dbus_connection_flush(conn);
//WriteLn('Request Sent');
// free message
dbus_message_unref(msg);
// block until we recieve a reply
dbus_pending_call_block(pending);
// get the reply message
msg := dbus_pending_call_steal_reply(pending);
if (msg = nil) then
begin
ErrorDbus('Reply Null');
Exit;
end;
// free the pending message handle
dbus_pending_call_unref(pending);
// read the parameters
if dbus_message_iter_init(msg, @args)=0 then
begin
ErrorDbus('No parameters in reply')
end else
begin
numparams:=1;
NoMoreParams:=false;
if GetByteParam then VisualizaBits(FEntradas,locbyte);
NextParam;
if GetByteParam then VisualizaBits(FSalidas, locbyte);
NextParam;
if GetStringParam then LabelEstadoLectura.caption:=LocString;
NextParam;
if GetStringParam then LabelEstadoSalida.caption:=LocString;
NextParam;
for i:=1 to 4 do
begin
if GetStringParam then PantallaDescarga[i].caption:=LocString;
NextParam;
end;
if GetIntegerParam then
DescargaBandejaPidiendo.caption:=IntToStr(LocInteger);
NextParam;
if GetIntegerParam then
DescargaBandejaBoca.caption:=IntToStr(LocInteger);
NextParam;
if GetStringParam then LabelEstadoEntrada.caption:=LocString;
NextParam;
for i:=1 to 4 do
begin
if GetStringParam then PantallaCarga[i].caption:=LocString;
NextParam;
end;
if GetIntegerParam then
CargaBandejaPidiendo.caption:=IntToStr(LocInteger);
NextParam;
if GetIntegerParam then CargaBandejaBoca.caption:=IntToStr(LocInteger);
NextParam;
if GetStringParam then for i:=1 to 7 do
DescargaGrid.Cells[i,1]:=ExtractWord(i,LocString,[',']);
NextParam;
if GetIntegerParam then if Initfifo or (LocInteger<>FifoSerial)
then GetFifo(LocInteger);
end;
// free reply
dbus_message_unref(msg);
end;
Bye
--
Luca
More information about the fpc-pascal
mailing list