[XS] direct access to the perl stack in XS code

Discussion in 'Perl Misc' started by Rainer Weikusat, Jul 8, 2013.

  1. I finally grew somewhat tired of the Sys::Syslog code which does too
    many weird things it shouldn't be doing (such as interfacing with the
    Windows event log :->) in Perl code, including downright stupid things
    such as using run-time translated strings for the priority constants
    and things which change the 'global' execution environment (bad thing
    for a routine supposed to generate diagnostic output). I've had a look
    at Unix::Syslog but don't quite like that, either, because of 'weird
    things' in the XS code ('hand-written' constant access functions,
    mapping constants to names with for loops) and things written in Perl
    which could equally well be implemented in C (message formatting).

    Since this should really be an exercise in non-coding aka "just call
    the C library routines and assume anything else is someone else's
    business" and I had an otherwise spare Sunday evening in front of me,
    I thought I could just run h2xs on the syslog.h file and see where
    that would get me. Things never turning out to be quite as beautiful
    as they should, some code does need to be written for that, in
    particular, there's no (sane) way to invoke a C 'variadic
    format-string function' with an a priori unknown set of arguments
    which came from perl.

    Perlapi(1) documents a function named
    sv_vsetpvfn which seemed suitable for the formatting part which can
    either work with a va_list or an array of SVs. At first, I thought of
    copying the arguments on the stack into an array but then, it occurred
    to me that the perl stack really ought to be such an array, already
    laying in front of my feet and ready to be used. The code I'm
    presently using for syslog which seems to be working fine is

    void
    syslog(__pri, __fmt, ...)
    int __pri
    char * __fmt
    INIT:
    char *msg;
    SV *msg_sv;
    bool dummy;
    CODE:
    if (items > 2) {
    msg_sv = sv_newmortal();
    sv_vsetpvfn(msg_sv, __fmt, sv_len(ST(1)), NULL,
    PL_stack_base + ax + 2, items - 2,
    &dummy);
    msg = SvPV_nolen(msg_sv);
    } else {
    msg = __fmt;
    }
    syslog(__pri, "%s", msg);

    Is there, excluding aesthetic/ philosophic aspects, a reason why I shouldn't be
    doing this?
     
    Rainer Weikusat, Jul 8, 2013
    #1
    1. Advertising

  2. Ben Morrow <> writes:
    > Quoth Rainer Weikusat <>:


    [syslog(3)]

    >> there's no (sane) way to invoke a C 'variadic format-string
    >> function' with an a priori unknown set of arguments
    >> which came from perl.

    >
    > No. This is because there's no (standard) way to invoke a variadic C
    > function with a dynamic argument list.


    Even if there was, the code would need to interpret the format string
    in order to determine the types of the arguments which need to be
    passed to the C library routine and convert the 'Perl values' as
    required. Which would then interpret the format string again. That's
    not particularly sane.

    >> Perlapi(1) documents a function named sv_vsetpvfn which seemed
    >> suitable for the formatting part which can either work with a
    >> va_list or an array of SVs.

    >
    > The only problem with using this is that is will not handle %m. You will
    > need to run through the format list, replace %m with %s, and insert
    > strerror into the argument list.


    If I cared that much about %m, I would change the formatting function
    to deal with it :)[*]. Otherwise, there's again the need to scan the
    format string twice and then either copy it a couple of times (what
    the existing syslog modules do) or do an arbitrary number of 'in the
    middle of an array' inserts. Omitting some features which can't be
    supported easily is better than providing them with the help of a
    quick and bad implementation punishing everyone.

    [*] I'm not yet using a forked perl and don't plan to start doing so
    unless I encounter a much more serious obstacle.

    [...]

    >> void
    >> syslog(__pri, __fmt, ...)
    >> int __pri
    >> char * __fmt
    >> INIT:
    >> char *msg;
    >> SV *msg_sv;
    >> bool dummy;
    >> CODE:
    >> if (items > 2) {
    >> msg_sv = sv_newmortal();
    >> sv_vsetpvfn(msg_sv, __fmt, sv_len(ST(1)), NULL,

    >
    > Calling sv_len here separately from the SvPV done by the typemap means
    > the format argument will be stringified twice.


    Thanks.

    [...]

    > Instead you should take a SV* argument, and use SvPV to retrieve string
    > value and length in one go. (I don't think you can reasonably use the
    > length(s) XS feature here.)
    >
    >> PL_stack_base + ax + 2, items - 2,

    >
    > I would probably write this &ST(2), but as you like.


    Some people like to pretend that 'C arrays' were something they're not
    really hard. That leads to expressions like &a[n] or even (as in this
    case) &a[n + m]. That's by definition the same as &*(a + n + m), that
    is a + n + m plus some kind of "jump to the left, then, jump quickly to
    the right and pretend you didn't move at all" prefix ...
     
    Rainer Weikusat, Jul 8, 2013
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Anan
    Replies:
    8
    Views:
    15,675
    John C. Bollinger
    Dec 8, 2004
  2. Surinder Singh
    Replies:
    1
    Views:
    1,207
    Richard Bos
    Dec 20, 2007
  3. Casey Hawthorne
    Replies:
    3
    Views:
    1,100
    Flash Gordon
    Nov 1, 2009
  4. Debajit Adhikary
    Replies:
    36
    Views:
    2,309
    Andre Kaufmann
    Feb 10, 2011
  5. CJM
    Replies:
    12
    Views:
    352
Loading...

Share This Page