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