This is an automated email from the git hooks/post-receive script. intrigeri pushed a commit to branch experimental in repository libnet-dbus-perl.
commit 149d28736d4fb98f9a19848f9008fa462298181d Author: Daniel P. Berrange <d...@berrange.com> Date: Tue Mar 29 19:37:22 2005 +0000 Merged introspection code from INTROSPECTION branch into mainline --- examples/example-client.pl | 3 + examples/example-service.pl | 25 ++- examples/example-signal-emitter.pl | 23 ++- examples/example-signal-receiver.pl | 13 +- lib/Net/DBus.pm | 107 +---------- lib/Net/DBus/Binding/Iterator.pm | 66 ++++--- lib/Net/DBus/Introspector.pm | 369 ++++++++++++++++++++++++++++++++++++ lib/Net/DBus/Object.pm | 38 ++-- lib/Net/DBus/RemoteObject.pm | 35 +++- t/40-introspector.t | 63 ++++++ 10 files changed, 581 insertions(+), 161 deletions(-) diff --git a/examples/example-client.pl b/examples/example-client.pl index 8c8fa42..5fb97ef 100644 --- a/examples/example-client.pl +++ b/examples/example-client.pl @@ -1,6 +1,9 @@ #/usr/bin/perl use Net::DBus; +use Carp qw(cluck carp); +#$SIG{__WARN__} = sub { cluck $_[0] }; +#$SIG{__DIE__} = sub { carp $_[0] }; my $bus = Net::DBus->session(); diff --git a/examples/example-service.pl b/examples/example-service.pl index 964b1dd..530dc74 100644 --- a/examples/example-service.pl +++ b/examples/example-service.pl @@ -22,7 +22,24 @@ use base qw(Net::DBus::Object); sub new { my $class = shift; my $self = $class->SUPER::new("/SomeObject", - ["HelloWorld"], + { + "SomeObject" => { + methods => { + "HelloWorld" => { + params => ["string"], + returns => [["array",["string"]]], + }, + "GetDict" => { + params => [], + returns => [["dict", ["string", "string"]]], + }, + "GetTuple" => { + params => [], + returns => [["struct", ["string", "string"]]], + } + }, + }, + }, @_); bless $self, $class; @@ -30,9 +47,11 @@ sub new { return $self; } + sub HelloWorld { my $self = shift; my $message = shift; + print "Do hello world\n"; print $message, "\n"; return ["Hello", " from example-service.pl"]; } @@ -40,11 +59,13 @@ sub HelloWorld { sub GetDict { my $self = shift; my $message = shift; + print "Do get dict\n"; return {"first" => "Hello Dict", "second" => " from example-service.py"}; } sub GetTuple { my $self = shift; my $message = shift; - return Net::DBus::dstruct(["Hello Tuple", " from example-service.py"]); + print "Do get tuple\n"; + return ["Hello Tuple", " from example-service.py"]; } diff --git a/examples/example-signal-emitter.pl b/examples/example-signal-emitter.pl index d095b2a..e4cec92 100644 --- a/examples/example-signal-emitter.pl +++ b/examples/example-signal-emitter.pl @@ -5,6 +5,11 @@ use Net::DBus::Reactor; use Net::DBus::Service; use Net::DBus::Object; +use Carp qw(confess cluck); + +$SIG{__WARN__} = sub { cluck $_[0] }; +$SIG{__DIE__} = sub { confess $_[0] }; + my $bus = Net::DBus->session(); my $service = Net::DBus::Service->new("org.designfu.TestService", $bus); @@ -21,7 +26,19 @@ use base qw(Net::DBus::Object); sub new { my $class = shift; my $self = $class->SUPER::new("/org/designfu/TestService/object", - ["emitHelloSignal"], + { + "org.designfu.TestService" => { + methods => { + "emitHelloSignal" => { + params => [], + returns => [], + }, + }, + signals => { + "hello" => [], + }, + }, + }, @_); bless $self, $class; @@ -31,7 +48,7 @@ sub new { sub emitHelloSignal { my $self = shift; - $self->emit_signal("org.designfu.TestService", - "hello"); + return $self->emit_signal("org.designfu.TestService", + "hello"); } diff --git a/examples/example-signal-receiver.pl b/examples/example-signal-receiver.pl index f870a0c..0a7e295 100644 --- a/examples/example-signal-receiver.pl +++ b/examples/example-signal-receiver.pl @@ -3,6 +3,11 @@ use Net::DBus; use Net::DBus::Reactor; +use Carp qw(confess cluck); + +#$SIG{__WARN__} = sub { cluck $_[0] }; +#$SIG{__DIE__} = sub { confess $_[0] }; + my $bus = Net::DBus->session(); my $service = $bus->get_service("org.designfu.TestService"); @@ -17,9 +22,11 @@ sub hello_signal_handler { $object->connect_to_signal("hello", \&hello_signal_handler); -# Tell the remote object to emit the signal -$object->emitHelloSignal(); - my $reactor = Net::DBus::Reactor->new(); $reactor->manage($bus->{connection}); + +$reactor->add_timeout(1000, Net::DBus::Callback->new(method => sub { + $object->emitHelloSignal(); +})); + $reactor->run(); diff --git a/lib/Net/DBus.pm b/lib/Net/DBus.pm index 47043cd..0c30818 100644 --- a/lib/Net/DBus.pm +++ b/lib/Net/DBus.pm @@ -5,25 +5,20 @@ use strict; use warnings; use Carp; + + +BEGIN { +our $VERSION = '0.0.1'; +require XSLoader; +XSLoader::load('Net::DBus', $VERSION); +} + use Net::DBus::Binding::Bus; use Net::DBus::Binding::Message; use Net::DBus::Binding::Value; use Net::DBus::RemoteService; -our $VERSION = '0.0.1'; - -use Exporter; - -use base qw(Exporter); -use vars qw(@EXPORT); - -@EXPORT = qw(dboolean dbyte dstring dint32 - duint32 dint64 duint64 ddouble - dstruct dpack); - -require XSLoader; -XSLoader::load('Net::DBus', $VERSION); sub system { my $class = shift; @@ -203,92 +198,6 @@ sub _signal_func { return $handled; } - -sub dboolean { - my $value = shift; - return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_BOOLEAN, - $value); -} - -sub dbyte { - my $value = shift; - return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_BYTE, - $value); -} - -sub dstring { - my $value = shift; - return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_STRING, - $value); -} - -sub dint32 { - my $value = shift; - return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_INT32, - $value); -} - -sub duint32 { - my $value = shift; - return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_UINT32, - $value); -} - -sub dint64 { - my $value = shift; - return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_INT64, - $value); -} - -sub duint64 { - my $value = shift; - return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_UINT64, - $value); -} - -sub ddouble { - my $value = shift; - return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_DOUBLE, - $value); -} - -sub dstruct { - my $value = shift; - return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_STRUCT, - $value); -} - -our %flags = ( - 'o' => &Net::DBus::Binding::Message::TYPE_BOOLEAN, - 'b' => &Net::DBus::Binding::Message::TYPE_BYTE, - 's' => &Net::DBus::Binding::Message::TYPE_STRING, - 'i' => &Net::DBus::Binding::Message::TYPE_INT32, - 'I' => &Net::DBus::Binding::Message::TYPE_UINT32, - 'l' => &Net::DBus::Binding::Message::TYPE_INT64, - 'L' => &Net::DBus::Binding::Message::TYPE_UINT64, - 'd' => &Net::DBus::Binding::Message::TYPE_DOUBLE, - ); - -sub dpack { - my $format = shift; - my @in = @_; - if (length $format != ($#in+1)) { - confess "incorrect number of arguments for format string"; - } - - my @out; - foreach my $flag (split //, $format) { - my $value = shift @in; - if (!exists $flags{$flag}) { - confess "unknown format flag '$flag'"; - } - push @out, Net::DBus::Binding::Value->new($flags{$flag}, - $value); - } - return @out; -} - - 1; __END__ diff --git a/lib/Net/DBus/Binding/Iterator.pm b/lib/Net/DBus/Binding/Iterator.pm index 7543174..f83662e 100644 --- a/lib/Net/DBus/Binding/Iterator.pm +++ b/lib/Net/DBus/Binding/Iterator.pm @@ -276,30 +276,20 @@ sub get_struct { sub append { my $self = shift; my $value = shift; + my $type = shift; - my $type; - if (@_) { - $type = shift; - } elsif (ref($value) eq "Net::DBus::Binding::Value") { - $type = $value->type; - $value = $value->value; - } else { - $type = &Net::DBus::Binding::Message::TYPE_STRING; - } - - #warn "Type $type value $value\n"; - - if (ref($value)) { - if (ref($value) eq "HASH") { - $self->append_dict($value); - } elsif (ref($value) eq "ARRAY") { - if ($type == &Net::DBus::Binding::Message::TYPE_STRUCT) { - $self->append_struct($value); - } else { - $self->append_array($value, $type); - } + if (ref($type) eq "ARRAY") { + my $maintype = $type->[0]; + my $subtype = $type->[1]; + + if ($maintype == &Net::DBus::Binding::Message::TYPE_DICT_ENTRY) { + $self->append_dict($value, $subtype); + } elsif ($maintype == &Net::DBus::Binding::Message::TYPE_STRUCT) { + $self->append_struct($value, $subtype); + } elsif ($maintype == &Net::DBus::Binding::Message::TYPE_ARRAY) { + $self->append_array($value, $subtype); } else { - confess "Unsupported reference type ", ref($value); + confess "Unsupported compound type ", $maintype; } } else { if ($type == &Net::DBus::Binding::Message::TYPE_BOOLEAN) { @@ -329,12 +319,21 @@ sub append_array { my $self = shift; my $array = shift; my $type = shift; - - my $sig = chr($type); + + die "array must only have one type" + if $#{$type} > 0; + + my $sig; + if (ref($type->[0])) { + $sig = chr($type->[0]->[0]); + } else { + $sig = chr($type->[0]); + } + my $iter = $self->_open_container(&Net::DBus::Binding::Message::TYPE_ARRAY, $sig); foreach my $value (@{$array}) { - $iter->append($value, $type); + $iter->append($value, $type->[0]); } $self->_close_container($iter); @@ -344,11 +343,17 @@ sub append_array { sub append_struct { my $self = shift; my $struct = shift; - + my $type = shift; + + if ($#{$struct} != $#{$type}) { + die "number of values does not match type"; + } + my $iter = $self->_open_container(&Net::DBus::Binding::Message::TYPE_STRUCT, undef); + my @type = @{$type}; foreach my $value (@{$struct}) { - $iter->append($value); + $iter->append($value, shift @type); } $self->_close_container($iter); @@ -358,7 +363,8 @@ sub append_struct { sub append_dict { my $self = shift; my $hash = shift; - + my $type = shift; + # XXX don't hardcode me - cf Python bindings my $sig = "{ss}"; my $iter = $self->_open_container(&Net::DBus::Binding::Message::TYPE_ARRAY, $sig); @@ -367,8 +373,8 @@ sub append_dict { my $value = $hash->{$key}; my $entry = $iter->_open_container(&Net::DBus::Binding::Message::TYPE_DICT_ENTRY, $sig); - $entry->append($key); - $entry->append($value); + $entry->append($key, $type->[0]); + $entry->append($value, $type->[1]); $iter->_close_container($entry); } $self->_close_container($iter); diff --git a/lib/Net/DBus/Introspector.pm b/lib/Net/DBus/Introspector.pm new file mode 100644 index 0000000..0edb420 --- /dev/null +++ b/lib/Net/DBus/Introspector.pm @@ -0,0 +1,369 @@ +=pod + + name => "org.foo.bar.Object" + interfaces => + "org.foo.bar.Wibble" => { + methods => { + foo => { + params => ["int32", "double", ["array", ["int32"]]], + return => ["string", "byte", ["dict", ["string", "variant"]]] + } + } + } + } + children => [ + introspector... + ]; + +=cut + +package Net::DBus::Introspector; + +use 5.006; +use strict; +use warnings; +use Carp; +use XML::Grove::Builder; +use XML::Parser::PerlSAX; + +use Net::DBus; +use Net::DBus::Binding::Message; + +our %simple_type_map = ( + "byte" => &Net::DBus::Binding::Message::TYPE_BYTE, + "bool" => &Net::DBus::Binding::Message::TYPE_BOOLEAN, + "double" => &Net::DBus::Binding::Message::TYPE_DOUBLE, + "string" => &Net::DBus::Binding::Message::TYPE_STRING, + "int32" => &Net::DBus::Binding::Message::TYPE_INT32, + "uint32" => &Net::DBus::Binding::Message::TYPE_UINT32, + "int64" => &Net::DBus::Binding::Message::TYPE_INT64, + "uint64" => &Net::DBus::Binding::Message::TYPE_UINT64, +); + +our %compound_type_map = ( + "array" => &Net::DBus::Binding::Message::TYPE_ARRAY, + "struct" => &Net::DBus::Binding::Message::TYPE_STRUCT, + "dict" => &Net::DBus::Binding::Message::TYPE_DICT_ENTRY, +); + + +our $VERSION = '0.0.1'; + +sub new { + my $class = shift; + my $self = {}; + my %params = @_; + + bless $self, $class; + + if (defined $params{xml}) { + $self->_parse($params{xml}); + } else { + $self->{name} = exists $params{name} ? $params{name} : die "name parameter is required"; + $self->{interfaces} = exists $params{interfaces} ? $params{interfaces} : die "interfaces parameter is required"; + $self->{children} = exists $params{children} ? $params{children} : []; + } + + $self->{interfaces}->{"org.freedesktop.DBus.Introspectable"} = { + methods => { + "Introspect" => { + params => [], + returns => ["string"], + } + } + }; + + $self->{methods} = {}; + $self->{signals} = {}; + foreach my $name (keys %{$self->{interfaces}}) { + my $interface = $self->{interfaces}->{$name}; + foreach my $method (keys %{$interface->{methods}}) { + $self->{methods}->{$method} = $interface->{methods}->{$method}; + } + foreach my $signal (keys %{$interface->{signals}}) { + $self->{signals}->{$signal} = $interface->{signals}->{$signal}; + } + } + + return $self; +} + +sub _parse { + my $self = shift; + my $xml = shift; + + my $grove_builder = XML::Grove::Builder->new; + my $parser = XML::Parser::PerlSAX->new(Handler => $grove_builder); + my $document = $parser->parse ( Source => { String => $xml } ); + + my $root = $document->{Contents}->[0]; + + $self->{name} = $root->{Attributes}->{name}; + $self->{interfaces} = {}; + foreach my $child (@{$root->{Contents}}) { + if (ref($child) eq "XML::Grove::Element" && + $child->{Name} eq "interface") { + $self->_parse_interface($child); + } + } +} + +sub _parse_interface { + my $self = shift; + my $node = shift; + + my $name = $node->{Attributes}->{name}; + $self->{interfaces}->{$name} = { + methods => {}, + signals => {}, + }; + + foreach my $child (@{$node->{Contents}}) { + if (ref($child) eq "XML::Grove::Element" && + $child->{Name} eq "method") { + $self->_parse_method($child, $name); + } elsif (ref($child) eq "XML::Grove::Element" && + $child->{Name} eq "signal") { + $self->_parse_signal($child, $name); + } + } +} + +sub _parse_method { + my $self = shift; + my $node = shift; + my $interface = shift; + + my $name = $node->{Attributes}->{name}; + my @params; + my @returns; + foreach my $child (@{$node->{Contents}}) { + if (ref($child) eq "XML::Grove::Element" && + $child->{Name} eq "arg") { + my $type = $child->{Attributes}->{type}; + my $direction = $child->{Attributes}->{direction}; + + if (exists $compound_type_map{lc $type}) { + my @subtype = $self->_parse_type($child); + if ($direction eq "in") { + push @params, [lc $type, \@subtype]; + } elsif ($direction eq "out") { + push @returns, [lc $type, \@subtype]; + } + } elsif (exists $simple_type_map{lc $type}) { + if ($direction eq "in") { + push @params, lc $type; + } elsif ($direction eq "out") { + push @returns, lc $type; + } + } + } + } + + $self->{interfaces}->{$interface}->{methods}->{$name} = { + params => \@params, + returns => \@returns, + } +} + +sub _parse_type { + my $self = shift; + my $node = shift; + + + my @types; + foreach my $child (@{$node->{Contents}}) { + if (ref($child) eq "XML::Grove::Element" && + $child->{Name} eq "type") { + my $name = $child->{Attributes}->{name}; + + if (exists $compound_type_map{lc $name}) { + my @subtype = $self->_parse_type($child); + push @types, [lc $name, \@subtype]; + } elsif (exists $simple_type_map{lc $name}) { + push @types, lc $name; + } + } + } + + return @types; +} + +sub _parse_signal { + my $self = shift; + my $node = shift; + my $interface = shift; + + my $name = $node->{Attributes}->{name}; + my @params; + foreach my $child (@{$node->{Contents}}) { + if (ref($child) eq "XML::Grove::Element" && + $child->{Name} eq "arg") { + my $type = $child->{Attributes}->{type}; + + if (exists $compound_type_map{lc $type}) { + my @subtype = $self->_parse_type($child); + push @params, [lc $type, \@subtype]; + } elsif (exists $simple_type_map{lc $type}) { + push @params, lc $type; + } + } + } + + $self->{interfaces}->{$interface}->{signals}->{$name} = + \@params; +} + +sub format { + my $self = shift; + + my $xml = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"' . "\n"; + $xml .= '"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">' . "\n"; + + return $xml . $self->to_xml(""); +} + +sub to_xml { + my $self = shift; + my $indent = shift; + + my $xml = ''; + $xml .= $indent . '<node name="' . $self->{name} . '">' . "\n"; + + foreach my $name (keys %{$self->{interfaces}}) { + my $interface = $self->{interfaces}->{$name}; + $xml .= $indent . ' <interface name="' . $name . '">' . "\n"; + foreach my $mname (keys %{$interface->{methods}}) { + my $method = $interface->{methods}->{$mname}; + $xml .= $indent . ' <method name="' . $mname . '">' . "\n"; + + foreach my $type (@{$method->{params}}) { + if (ref($type) eq "ARRAY") { + $xml .= $indent . ' <arg type="' . $type->[0] . '" direction="in">' . "\n"; + $xml .= $self->to_xml_type($type->[1], $indent . ' '); + $xml .= $indent . ' </arg>' . "\n"; + } else { + $xml .= $indent . ' <arg type="' . $type . '" direction="in"/>' . "\n"; + } + } + + foreach my $type (@{$method->{returns}}) { + if (ref($type) eq "ARRAY") { + $xml .= $indent . ' <arg type="' . $type->[0] . '" direction="out">' . "\n"; + $xml .= $self->to_xml_type($type->[1], $indent . ' '); + $xml .= $indent . ' </arg>' . "\n"; + } else { + $xml .= $indent . ' <arg type="' . $type . '" direction="out"/>' . "\n"; + } + } + + + $xml .= $indent . ' </method>' . "\n"; + } + foreach my $sname (keys %{$interface->{signals}}) { + my $signal = $interface->{signals}->{$sname}; + $xml .= $indent . ' <signal name="' . $sname . '">' . "\n"; + + foreach my $type (@{$signal}) { + if (ref($type) eq "ARRAY") { + $xml .= $indent . ' <arg type="' . $type->[0] . '">' . "\n"; + $xml .= $self->to_xml_type($type->[1], $indent . ' '); + $xml .= $indent . ' </arg>' . "\n"; + } else { + $xml .= $indent . ' <arg type="' . $type . '"/>' . "\n"; + } + } + $xml .= $indent . ' </signal>' . "\n"; + } + + $xml .= $indent . ' </interface>' . "\n"; + } + + foreach my $child (@{$self->{children}}) { + if (ref($child) eq "Net::DBus::Introspector") { + $xml .= $child->to_xml($indent . " ") . "\n"; + } else { + $xml .= $indent . ' <node name="' . $child . '"/>' . "\n"; + } + } + $xml .= $indent . "</node>"; +} + + +sub to_xml_type { + my $self = shift; + my $type = shift; + my $indent = shift; + my $xml = ''; + foreach my $subtype (@{$type}) { + if (ref($subtype) eq "ARRAY") { + $xml .= $indent . ' <type name="' . $subtype->[0] . '">' . "\n"; + $xml .= $self->to_xml_type($subtype->[1], $indent . ' '); + $xml .= $indent . ' </type>' . "\n"; + } else { + $xml .= $indent . ' <type name="' . $subtype . '"/>' . "\n"; + } + } + return $xml; +} + +sub encode { + my $self = shift; + my $message = shift; + my $type = shift; + my $name = shift; + my $direction = shift; + my @args = @_; + + die "no introspection data for such $name ($type)" unless exists $self->{$type}->{$name}; + + my @types = $type eq "signals" ? + @{$self->{$type}->{$name}} : + @{$self->{$type}->{$name}->{$direction}}; + + die "expected " . int(@types) . " params, but got " . int(@args) + unless $#types == $#args; + + my $iter = $message->iterator(1); + foreach my $t ($self->convert(@types)) { + $iter->append(shift @args, $t); + } +} + + +sub convert { + my $self = shift; + my @in = @_; + + my @out; + foreach my $in (@in) { + if (ref($in) eq "ARRAY") { + my @subout = $self->convert(@{$in->[1]}); + die "unknown compound type " . $in->[0] unless + exists $compound_type_map{lc $in->[0]}; + push @out, [$compound_type_map{lc $in->[0]}, \@subout]; + } else { + die "unknown simple type " . $in unless + exists $simple_type_map{lc $in}; + push @out, $simple_type_map{lc $in}; + } + } + return @out; +} + +sub decode { + my $self = shift; + my $message = shift; + my $type = shift; + my $name = shift; + my $direction = shift; + my @args = @_; + + die "no introspection data for such $name ($type)" unless exists $self->{$type}->{$name}; + + my @type = $type eq "signal" ? + @{$self->{$type}->{$name}} : + @{$self->{$type}->{$name}->{$direction}}; + + +} diff --git a/lib/Net/DBus/Object.pm b/lib/Net/DBus/Object.pm index 1ee77dc..07340af 100644 --- a/lib/Net/DBus/Object.pm +++ b/lib/Net/DBus/Object.pm @@ -8,6 +8,7 @@ use Carp; our $VERSION = '0.0.1'; use Net::DBus::RemoteObject; +use Net::DBus::Introspector; use Net::DBus::Binding::Message::Error; use Net::DBus::Binding::Message::MethodReturn; @@ -16,10 +17,10 @@ sub new { my $self = {}; $self->{object_path} = shift; - - my $methods = shift; - $self->{methods} = {}; - map { $self->{methods}->{$_} = 1 } @{$methods}; + + my $interfaces = shift; + $self->{introspector} = Net::DBus::Introspector->new(name => $self->{object_path}, + interfaces => $interfaces); $self->{service} = shift; @@ -35,18 +36,28 @@ sub new { } +sub Introspect { + my $self = shift; + #warn "Asked for introspection data\n"; + my $xml = $self->{introspector}->format; + #warn $xml; + return $xml; +} + + sub emit_signal { my $self = shift; my $interface = shift; my $signal_name = shift; + my @args = @_; my $signal = Net::DBus::Binding::Message::Signal->new(object_path => $self->{object_path}, interface => $interface, signal_name => $signal_name); - my $iter = $signal->iterator(1); - foreach my $ret (@_) { - $iter->append($ret); - } + + $self->{introspector}->encode($signal, "signals", $signal_name, "params", @args); $self->{service}->get_bus()->get_connection()->send($signal); + + return (); } sub _dispatch { @@ -68,15 +79,8 @@ sub _dispatch { description => $@); } else { $reply = Net::DBus::Binding::Message::MethodReturn->new(call => $message); - if (@ret == 1) { - my $iter = $reply->iterator(1); - $iter->append(shift @ret); - } elsif (@ret > 1) { - my $iter = $reply->iterator(1); - foreach my $ret (@ret) { - $iter->append($ret); - } - } + + $self->{introspector}->encode($reply, "methods", $method_name, "returns", @ret); } } else { $reply = Net::DBus::Binding::Message::Error->new(replyto => $message, diff --git a/lib/Net/DBus/RemoteObject.pm b/lib/Net/DBus/RemoteObject.pm index 78ffbca..811d3d1 100644 --- a/lib/Net/DBus/RemoteObject.pm +++ b/lib/Net/DBus/RemoteObject.pm @@ -9,6 +9,7 @@ our $VERSION = '0.0.1'; our $AUTOLOAD; use Net::DBus::Binding::Message::MethodCall; +use Net::DBus::Introspector; sub new { my $class = shift; @@ -17,12 +18,34 @@ sub new { $self->{service} = shift; $self->{object_path} = shift; $self->{interface} = shift; - + bless $self, $class; + $self->{introspector} = @_ ? shift : $self->_introspect(); + return $self; } +sub _introspect { + my $self = shift; + + my $call = Net::DBus::Binding::Message::MethodCall-> + new(service_name => $self->{service}->get_service_name(), + object_path => $self->{object_path}, + method_name => "Introspect", + interface => "org.freedesktop.DBus.Introspectable"); + + my $reply = $self->{service}-> + get_bus()-> + get_connection()-> + send_with_reply_and_block($call, 5000); + + my $iter = $reply->iterator; + my $xml = $iter->get(&Net::DBus::Binding::Message::TYPE_STRING); + + return Net::DBus::Introspector->new(xml => $xml); +} + sub connect_to_signal { my $self = shift; my $signal_name = shift; @@ -54,17 +77,15 @@ sub AUTOLOAD { method_name => $method, interface => $self->{interface}); - my $iter = $call->iterator(1); - foreach my $arg (@_) { - $iter->append($arg); - } - + $self->{introspector}->encode($call, "methods", $method, "params", @_); + my $reply = $self->{service}-> get_bus()-> get_connection()-> send_with_reply_and_block($call, 5000); - my @reply = $reply->get_args_list; + my @reply = $reply->get_args_list(); + #my @reply = $self->{introspector}->decode($reply, $method, "return"); return wantarray ? @reply : $reply[0]; } diff --git a/t/40-introspector.t b/t/40-introspector.t new file mode 100644 index 0000000..77512de --- /dev/null +++ b/t/40-introspector.t @@ -0,0 +1,63 @@ +# -*- perl -*- +use Test::More tests => 2; +BEGIN { + use_ok('Net::DBus::Introspector'); + }; + + +TEST_ONE: { + my $other_object = Net::DBus::Introspector->new( + name => "org.example.OtherObject", + interfaces => { + "org.example.SomeInterface" => { + methods => { + "hello" => { + params => ["int32", "int32", ["struct", ["int32","byte"]]], + returns => ["int32"], + }, + "goodbye" => { + params => [["array", [["struct", ["int32", "string"]]]]], + returns => ["string", "string"], + }, + }, + signals => { + "meltdown" => ["int32", "byte"], + } + } + }); + my $object = Net::DBus::Introspector->new( + name => "org.example.Object", + interfaces => { + "org.example.SomeInterface" => { + methods => { + "hello" => { + params => ["int32", "int32", ["struct", ["int32","byte"]]], + returns => ["int32"], + }, + "goodbye" => { + params => [["array", [["struct", ["int32", "string"]]]]], + returns => ["string", "string"], + }, + }, + signals => { + "meltdown" => ["int32", "byte"], + }, + }, + "org.example.OtherInterface" => { + methods => { + "hitme" => { + params => ["int32", "uint32"], + return => [], + } + } + }, + }, + children => [ + "org.example.AnotherObject", + $other_object, + ]); + + isa_ok($object, "Net::DBus::Introspector"); + + warn $object->format; +} -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libnet-dbus-perl.git _______________________________________________ Pkg-perl-cvs-commits mailing list Pkg-perl-cvs-commits@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-perl-cvs-commits