Paul Lindner wrote:
> If you look you'll see that the new() method is written in C. It
> should be blessing itself into the passed in class, not using
> Apache::Request.
You're right- except that this is exactly how the Apache class,
from which Apache::Request is derived, expects to be subclassed.
It requires all derived classes to override new().
> My XS is a little foggy, but it appears that these lines should be
> modified to use the passed in class:
> CLEANUP:
> apreq_add_magic(ST(0), robj, RETVAL);
> which ends up as:
> ST(0) = sv_newmortal();
> sv_setref_pv(ST(0), "Apache::Request", (void*)RETVAL);
No- that code in Request.c comes from this line in the libapreq
typemap:
T_APROBJ
sv_setref_pv($arg, \"${ntype}\", (void*)$var);
$ntype is converted to "Apache::Request" by xsubpp. We could
pull the package info from SvPV(class), but then the same fix
probably should be incorporated into modperl as well.
> In any case all you need to do to get around this is define your own
> new method and call the Apache::Request object directly and store it
> as the value 'r'.. Here's an example:
> sub new {
> my ($class, $r) = @_;
> return bless { r => Apache::Request->new($r),
> }, $class;
> }
Yes, exactly. sv_2apreq will look for an Apache::Request object
attribute in the r or _r keys: the behavior is consistent
with the eagle's Chapter 7 section on "Subclassing the Apache
Class":
"To be successful, the new subclass must add Apache (or another
Apache subclass) to its @ISA array. In addition, the subclass's
new() method must return a blessed hash reference which contains
either an r or _r key. This key must point to a bona fide Apache
object."
The reason this also works OK with a derived class like
Apache::Request is that an the ApacheRequest C struct has a
request_rec pointer as its *first* attribute, so a cast from
(ApacheRequest *) to (request_rec *) will be safe.
--
Joe Schaefer