perlreturn-typepdlinline-c

Perl Inline::C return pdl or 0 on failure


I am building a module which connects to a camera, takes a picture, and reads the data into a piddle. All of this takes place in an Inline::C command. Using the procedure in the PDL documentation I can create a pdl * and return it. However the camera could fail to take a picture in which case I would like to return 0 as per the usual covention my $pic_pdl = $Camera->TakePicture or die "Failed to take image". This seems to mean that I will need to use the Inline_Stack_Push mechanism but I am not sure how to properly convert the pdl * into an SV*. Also I would like to, if possible, set $! with the error code too. Can this be done in Inline?


Solution

  • The pdl* is converted to an SV by code found in the typemap.

    $ cat `perl -E'use PDL::Core::Dev; say PDL_TYPEMAP'`
    TYPEMAP
    pdl*    T_PDL
    pdl *   T_PDL
    Logical T_IV
    float   T_NV
    
    INPUT
    
    T_PDL
            $var = PDL->SvPDLV($arg)
    
    
    OUTPUT
    
    T_PDL
            PDL->SetSV_PDL($arg,$var);
    

    If I read that right, you should be able to do something like:

    SV* my_new {
        pdl* p = NULL;
    
        ...
    
        if (error) {
            if (p)
                free(p);  /* I think */
            return &PL_sv_undef;
        } else {
            SV* rv = newSV(0);
            PDL->SetSV_PDL(rv, p);
            return rv;
        }
    }
    

    As for $!, it's simply an interface to C's errno. Simply set errno.

    $ perl -E'use Inline C => "void f(int i) { errno = i; }"; f($ARGV[0]); say 0+$!; say $!;' 2
    2
    No such file or directory
    
    $ perl -E'use Inline C => "void f(int i) { errno = i; }"; f($ARGV[0]); say 0+$!; say $!;' 3
    3
    No such process
    
    $ perl -E'use Inline C => "void f(int i) { errno = i; }"; f($ARGV[0]); say 0+$!; say $!;' 4
    4
    Interrupted system call