develooper Front page | perl.perl5.porters | Postings from March 2001

Typemap oddity

From:
Tim Jenness
Date:
March 18, 2001 20:10
Subject:
Typemap oddity
Message ID:
Pine.LNX.4.30.0103181740290.23475-100000@lapaki.jach.hawaii.edu

Hi,

   I've been looking through the default typemap file trying to make sense
of some of it (some of the entries are completely undocumented and not
in use by any of the standard perl source). I've got a few questions on
them and I'm fully aware that the problem might be with my lack of
understanding so please let me know.

1. The INPUT entries for T_AVREF and T_HVREF (T_CVREF as well I suppose)
don't look right to me. They have the form:

T_AVREF
	if (sv_isa($arg, \"${ntype}\"))
	    $var = (AV*)SvRV($arg);
	else
	    Perl_croak(aTHX_ \"$var is not of type ${ntype}\")

This ends up with the following C code:

        if (sv_isa(ST(0), "AVPtr"))
            avref = (AV*)SvRV(ST(0));
        else
            croak("avref is not of type AVPtr");

If you do pass in a reference to an array this always fails because it
is not an "AVPtr" it is a reference to an AV. If this is to work there has
to be a way to make the reference point to an AVPtr - this just seems
wrong to me.

I would have expected a typemap of:

        if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV)
                $var = (AV*)SvRV($arg);
        else
                Perl_croak(aTHX_ \"$var is not of type AV\")


and this works as I expect.

(2) T_ARRAY  INPUT

The INPUT section for T_ARRAY contains:

T_ARRAY
	$var = $ntype(items -= $argoff);
	U32 ix_$var = $argoff;
	while (items--) {
	    DO_ARRAY_ELEM;
	}

If used with a type of "intArray *" this assumes a function of
intArrayPtr() to allocate the memory for the array (fair enough) and then
loops over each element in the array. Unfortunately ix_$var is used as an
index into the array and it is not incremented during the while loop.
Another problem is that xsubpp sees tge "\t$var" and assumes that the
decalaration fits on a single line - this leads to problems if RETVAL is
defined or PREINIT block is used since the declarations are in the wrong
place. The fix is to use the following definition for T_ARRAY:

T_ARRAY
        U32 ix_$var = $argoff;
        $var = $ntype(items -= $argoff);
        while (items--) {
                DO_ARRAY_ELEM;
                ix_$var++;
        }

Since now the block will be moved after the RETVAL declaration.

There can also be a problem related to DO_ARRAY_ELEM unless you are
careful of your type because it only replaces $ntype with $subtype in the
entry rather than $type.

(3) T_ARRAY OUTPUT

I assume the T_ARRAY OUTPUT typemap entry is meant to be used to copy the
contents of an array on to the argument stack for return. It uses
"$var.size" to determine the size - can someone explain to me how that
works if $var is meant to be a pointer to the first element of the array?
I see similar style in T_DATAUNIT (what is that for anyway?)

Is the intention for xsubpp to generate a new variable as a
concatentation? ie perl $var . "size", if so that is not happening. I
would be happy for the for the size to be stored in
xxsize for array variable xx. Currently the C code contains "xx.size" and
it complains about structure members (unsurprisingly).

(4) T_REFREF uses sv_setrefref but I can't find that function anywhere in
perl.

Finally, does anyone know what T_PTRDESC is for?

There is so much undocumented "magic" in xsubpp it is a little scary to
look inside.

I will submit patches for these if I don't get stamped on :-)

Thanks

-- 
Tim Jenness
JAC software
http://www.jach.hawaii.edu/~timj





nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About