On Wed, Sep 17, 2003 at 11:39:54AM +1000 Dave Horsfall wrote:
> Pardon me if this is a FANQ (Freq. Asked Newbie Question), but I cannot
> find any references to what I want to do.
> 
> I'm porting some legacy Perl/C code; it was originally done under Perl3
> (hacked into the function table), thence Perl4 (via userinit() etc).  I
> have the dubious honour of converting it into Perl5/XS.
> 
> Most Perl/C calls take a variable number of string arguments, and this is
> where I'm coming unstuck.  I've studied both perlxs and perlxstut until
> I'm practically dreaming XS, but I still cannot find a clear answer.
> 
> Let's take an example of a user-defined Perl function:
> 
>     $return = &uni_access("record", "key1", "key2");
> 
> This looks up a table "record" in a Unify database, using the supplied
> arguments as the key (in this case, a combination key), returning a
> success code (as a side-effect, the record is made "current", for later
> access).
> 
> With Perl3 and Perl4, it was relatively easy (although it was before my
> time), but I cannot work out how to do it in XS.  I figured I would call
> the C hook with an extra argument to specify the number of following
> strings e.g. a prototype like:
> 
> int
> uni_access(const char * record, ...)
>   C_ARGS:
>     record, items-1, ...
>   OUTPUT:
>     RETVAL
> 
> but that didn't work (syntax error on "...").  I thought about massaging
> the arguments into a list, but couldn't see how.

I don't think you need C_ARGS for that. Your XSUB should begin like
this (for instance):

    int
    uni_access(record, ...)
            char *record;   /* const char * may not be in typemap */
        PREINIT:
            char **args;
            register int i;
        CODE:
            New(1, args, items-1, char*);
            for (i = 1; i < items; i++) 
                *args++ = SvPV_nolen(ST(i));
            /* now you have "key1" in args[0] and "key2" in args[1] */
            ...
            RETVAL = bla();
        OUTPUT:
            RETVAL

> I implemented the XS stuff as a callable C library, but I have the freedom
> to change it (and had to, anyway).
> 
> So you can see my dilemma; I need to tell the underlying C code how many
> arguments there are (I cannot change the Perl calls).

Essentially, when working with variadic argument lists, you have the
special variable 'items' telling you how many arguments were passed. You
can then use ST(i) (or one of the POP? macros) to access the scalar
variables lying on the stack.

You can find more on that in perlxs.pod. See "Variable-length Parameter
Lists".

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval

Reply via email to