pileofrogs has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks

I'm working on making the unix saved id c functions available in perl. (See Unix::SavedIDs.) The c interface when setting id values is:

setresuid(ruid,euid,suid);

I would like to accommodate the situation where a user only wants to set the suid, IE I want this to work:

setresuid(undef,undef,$suid);

But XS seems to take a bleak view of sending undef as a parameter. I can set default values, so:

setresuid($ruid,$euid)

Works, but that doesn't help the instance where someone specifically passes undef as an arg.

The C functions accept '-1' to leave a value unchanged, so what I need to do is change undef to -1. I'd rather not require my users to say '-1' in a perl script where the perlish thing to do would be to say undef.

Thanks!
--Pileofrogs

Replies are listed 'Best First'.
Re: Passing undef to XSUB
by kyle (Abbot) on May 07, 2008 at 20:35 UTC

    It's a cheap solution, but I would probably write a wrapper.

    sub setresuid { # force @_ to have three elements $#_ = 2; # replace undefs in @_ with -1 for ( @_ ) { $_ = -1 if ! defined $_; } # magic goto the real setresuid goto &real_setresuid; }
Re: Passing undef to XSUB
by educated_foo (Vicar) on May 07, 2008 at 21:21 UTC
    The wrapper's easier and probably better (e.g. it's easy to support keyword parameters), but you can also take raw SVs in your XS code, like so:
    int foo(a,b) SV * a SV * b PREINIT: int aa, bb; CODE: aa = SvIOK(a) ? SvIV(a) : -1; bb = SvIOK(b) ? SvIV(b) : -1; RETVAL = aa * bb; OUTPUT: RETVAL
      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
        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
        Not for me -- int* doesn't appear to have a typemap for me (perl 5.8.8).