Posted on 2009-09-15 15:05:13-07 by jerome
Retrieving or thawing arbitrary OIO-based classes

I am trying to send OIO objects through IPC between processes on two different hosts. I have not been able to do so unless the receiving process has a proper 'use' statement for the package of the object being received. This prevents me from being able to send and receive "arbitrary" objects, i.e objects of a class not known at compile time by the receiving process. I have included a simple example below that does not rely on IPC but exhibits the same behavior (for what I believe are the same reasons).

Put in Foo.pm
package Foo;{ use strict; use warnings; use Object::InsideOut qw(Storable); my @bar :Field :Arg(Name=>'bar', Mandatory=>1); } 1;
Put in unload.pl
use strict; use warnings; use lib '.'; use Foo; my $file = 'object.stor'; my $object = Foo->new( bar => 10 ); $object->store($file);
Put in load.pl
use strict; use warnings; use Storable qw(retrieve); my $file = 'object.stor'; my $object = retrieve($file);

Run unload.pl and then load.pl. You should see this error: OIO::Args error: Unknown field name for class 'Foo': bar Package: Storable File: blib/lib/Storable.pm (autosplit into blib/lib/auto/Storable/_retrieve.al) Line: 331 Does this make sense? Is there any way to accomplish this? Jerome

Direct Responses: 11449 | Write a response
Posted on 2009-09-15 16:49:06-07 by jdhedden in response to 11448
Re: Retrieving or thawing arbitrary OIO-based classes
The 'data' for an OIO object is not stored in the object itself, but in lists/hashes within the object's class. Therefore the class must first exist in order for there to be a place to store the object data.

My suggestion is to do this in two steps:
1. First send over the class, and have the receiving end load that class using the following:
sub load_class { my $class = $_[0]; eval "require $class"; if ($@) { die("Failed to load $class: ".$@); } eval "$class->new()"; }
2. Then send over the object as you're doing now.

The last line in the subroutine is needed to ensure that $class is loaded and initialized properly. Hope this helps.
Direct Responses: 11451 | Write a response
Posted on 2009-09-15 18:01:40-07 by jerome in response to 11449
Re: Retrieving or thawing arbitrary OIO-based classes

Thanks for your prompt response. I actually tried something similar while troubleshooting but without the last call to 'new'. Your example assumes though that the receiving process knows how to instantiate $class. That won't be the case for me. Am I right to think that the sole purpose of your call to 'new' is to run 'initialize'? Before posting to this forum I realized that calling (a hacked-up version of) 'initialize' before thawing seems to do the trick as well. Would it make sense to allow users to do something like this instead?:

sub load_class { my $class = $_[0]; eval "require $class"; if ($@) { die("Failed to load $class: ".$@); } $class->initialize; }
Direct Responses: 11452 | Write a response
Posted on 2009-09-15 18:12:11-07 by jerome in response to 11451
Re: Retrieving or thawing arbitrary OIO-based classes
Oh that's why you wrapped the call to 'new' with an eval. Since the recipient won't know how to instantiate the class, the call to new is unlikely to succeed but it will only fail after calling 'initialize', right?. Let me try that in the real app. Thanks again.
Direct Responses: Write a response
Perl Weekly newsletter
A free weekly newsletter for people who are busy to read all the blogs. click here to check it out.