You can indeed play games with references closures. Here is a solution that does both:
package MyModule;
use File::Rsync;
# In some local scope
my $rsync = File::Rsync->new({
outfun => bind_args(\&capture_messages, \ my $out),
errfun => bind_args(\&capture_messages, \ my $err),
});
# Somewhere else
sub capture_messages {
my ($string_ref, $message, $type) = @_;
$$string_ref .= $message . "\n";
}
sub bind_args {
my ($func, @args) = @_;
sub {$func->(@args, @_)};
}
A bit sophisticated, but now the output is captured in a variable that is local to wherever your rsync declaration is done.