http://www.perlmonks.org?node_id=589156


in reply to Re^3: Dynamically wrapping ancestor method calls
in thread Dynamically wrapping ancestor method calls

Out of interest, may I ask about the the original problem which is being addressed by the automagic wrappering?

I'm the author of Audio::XMMSClient. This module provides an asynchronous interface th xmms2's client library. This is quite powerful but not very easy to use, especially very simple scripts or unit tests which don't need the async interface most of the time.

Therefor I wanted to write a wrapper, Audio::XMMSClient::Sync, around it that does just the same as Audio::XMMSClient does on all method calls, except for those which return some kind of request handle to be used in asynchronous clients. In that case it should just block until the request is completed, unpack the response into some perl structure and return that.

That way code that looked like that with the async api..

my $con = Audio::XMMSClient->new(...); $con->connect or die $con->last_error; my $res = $con->medialib_get_info( $some_song ); $res->wait; my $value = $res->value;

becomes that..

my $con = Audio::XMMSClient::Sync->new(...); $con->connect or die $con->last_error; my $value = $con->medialib_get_info( $some_song );

Cheers, Flo

Replies are listed 'Best First'.
Re^5: Dynamically wrapping ancestor method calls
by jbert (Priest) on Dec 11, 2006 at 21:37 UTC
    Ah, I see.

    So you could achieve what you want by putting a wrapper function around the return statements of the relevant methods in Audio::XMMSClient.

    return $s->_process_handle($handle);
    where _process_handle just returns its arg for async behaviour or does the sync-wait-and-return-data for the sync behaviour. You could select between the two either by subclassing (and overriding _process_handle), or even passing in sync => 0/1 to the ctor.

    If that isn't palatable for some reason, this sounds a little bit like a job for that modern buzzword Aspect Oriented Programming. This isn't really my area of expertise, but as I understand it, it allows you to effectively install pre- or post- handlers into your existing codebase, selected by various criteria. Adding handlers to massage the return values of a given class sounds within it's remit.

    I suspect that under the hood it is doing the same symbol table walking we've talked about before, but that should work OK in your case I think.

      That is indeed a solution that would work. Unfortunately Audio::XMMSClient is written in XS. Therefor adding that wrapper around the according return statements would be somewhat painful unless I add some pure-perl wrapper to all XS functions, which I don't want for obvious reasons.

      I already thought of using Moose and register a function to be called after a given function, but unfortunately this has the same problem as the subclassing approach: I need to have a list of all relevant functions. But as this changes frequently as the libxmmsclient API isn't stable yet and there have been large changes merged recently in the development branch I don't really want that.

      Cheers, Flo