in reply to Re: Passing undef to XSUB
in thread Passing undef to XSUB

Would int* also work? Like in
int foo(ap,bp) int* ap int* bp PREINIT: int a, b; CODE: a = ap ? *ap : -1; b = bp ? *bp : -1; RETVAL = a * b; OUTPUT: RETVAL

Replies are listed 'Best First'.
Re^3: Passing undef to XSUB
by syphilis (Archbishop) on May 08, 2008 at 00:49 UTC
    Would int* also work?

    No, but int would:
    int foo(ap,bp) int ap int bp PREINIT: int a, b; CODE: a = ap ? ap : -1; b = bp ? bp : -1; RETVAL = a * b; OUTPUT: RETVAL
    Though, if warnings are enabled, that produces a "Use of uninitialized value in subroutine entry..." for each undef that's passed to it - no such warning with educated_foo's rendition.

    Cheers,
    Rob
      It (presumably) compiles and runs, but I wouldn't say it works. Not only does it introduce a warning, it gives incorrect results for arguments equal to zero.
        it gives incorrect results for arguments equal to zero

        Yes ... I had missed the important point that 0 ought to be evaluated as 0 (and not -1).

        Now I understand what your speculative code was driving at.

        Cheers,
        Rob

      I don't know much about XS, but I wonder if this code is able to distinguish between when it's passed undef and when it's passed 0. That is, can it see the difference between foo( undef, undef ) and foo( 0, 0 )? It seems to me the "uninitialized value" warning is undef getting turned into 0.

        It seems to me the "uninitialized value" warning is undef getting turned into 0

        Yes, I think that's right:
        use warnings; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'EOC'; void foo(int a) {} void bar(SV * a) {} void baz(SV * a) { int i = (int)SvIV(a); } EOC $u = undef; foo($u); # warning bar($u); # no warning baz($u); # warning
        Cheers,
        Rob
Re^3: Passing undef to XSUB
by educated_foo (Vicar) on May 07, 2008 at 23:29 UTC
    Not for me -- int* doesn't appear to have a typemap for me (perl 5.8.8).
      Thanks