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

Reply via email to