C interface design question 
Author Message
 C interface design question

I am building a module that interfaces to C library that is mostly
comprised of functions that are supposed to be called like:

   status = func(handle, inarg1, inarg2, &outarg1, &outarg2);

The number of arguments vary, but I have up to 6 outargs in one case, a
mixture of integral and string values. What is the best way to represent
this in perl? I have so far tried one version (somewhat patterned after
the POSIX localeconf):

   ($status, $hashref) = func($handle, inarg1, inarg2);

Where hashref then contains the indivdiual outargs. But this does not cope
well if one of the outargs is optional in the C function by specifying
NULL and is computationally expensive to calculate. Currently all
arguments are always computed, as my xsub does never specify NULL for any
outarg. Is there a better way to represent this kind of function in perl?
--
Jens-Uwe Mager <pgp-mailto:62CFDB25>



Wed, 20 Sep 2000 03:00:00 GMT  
 C interface design question

) I am building a module that interfaces to C library that is mostly
) comprised of functions that are supposed to be called like:
)
)    status = func(handle, inarg1, inarg2, &outarg1, &outarg2);
)
) The number of arguments vary, but I have up to 6 outargs in one case, a
) mixture of integral and string values. What is the best way to represent
) this in perl? I have so far tried one version (somewhat patterned after
) the POSIX localeconf):
)
)    ($status, $hashref) = func($handle, inarg1, inarg2);
)
) Where hashref then contains the indivdiual outargs. But this does not cope
) well if one of the outargs is optional in the C function by specifying
) NULL and is computationally expensive to calculate. Currently all
) arguments are always computed, as my xsub does never specify NULL for any
) outarg. Is there a better way to represent this kind of function in perl?

First, I'd decide the proper XS interface and then decide what
Perl interface you want.

For maximum ease and efficiency, make the XS interface mostly
identical to the C interface:

    $status= func( $handle, $inarg1, $inarg2, $outarg1, [], $outarg3 );

where C<[]> means NULL in C.  Depending on the data type of the
out args, you'll probably need to make sure each out arg has
enough room for the result (for structs), or is exactly the right
type for the result (for simple data types).  In the second case,
I've used this in typemap:

    short *     T_IVBUF
    int *       T_IVBUF
    long *      T_IVBUF
    INPUT
    T_IVBUF
            if(  null_arg($arg)  )
                $var= NULL;
            else
                *( $var= ($type) _alloca( sizeof(*($var)) ) )= SvIV($arg)
    OUTPUT
    T_IVBUF
            if(  ! null_arg($arg)  &&  ! SvREADONLY($arg)  )
                sv_setiv( $arg, (IV)*($var) );

which won't work if you don't has alloca().  null_arg() is a macro
that goes in your *.xs file and is shown below.

In the first case, I have macros that are okay but should be
better but I'm not sure I can do that without enhancements to
XS itself.  What you need for fixed-size structures is:

#ifndef DEBUGGING
# define        Debug(list)     /*Nothing*/
#else
# define        Debug(list)     ErrPrintf list
# include <stdarg.h>
    static void
    ErrPrintf( const char *fmt, ... )
    {
      va_list alist;
      static char *env= NULL;
        if(  NULL == env  ) {
            if(  NULL == ( env= getenv("DEBUG_XS_ARGS") )  )
                env= "";
        }
        if(  '\0' == *env  )
            return;
        va_start( alist, fmt );
        vfprintf( stderr, fmt, alist );
        va_end( alist );
    }
#endif /* DEBUGGING */

/* Is an argument `[]', meaning we should pass `NULL'? */
#define null_arg(a)     (  SvROK(a)  &&  SVt_PVAV == SvTYPE(SvRV(a))    \
                           &&  -1 == av_len((AV*)SvRV(a))  )

/* Minimum buffer size to use on first call: */
#define MIN_GROW_SIZE   8

/* Used in Debug() messages to show which macro call is involved: */
#define string(arg) #arg

/* Grow a buffer to a fixed data type: */
#define grow_buf_typ( pBuf,svBuf, Type )        do {                    \
        Debug(( "grow_buf_typ( %s,[%s, %s ); 0x%lX==0x%lX %ld\n",       \
          string(pBuf), strchr(string(svBuf),'('), string(Type),        \
          pBuf, SvPVX(svBuf), sizeof(Type) ));                          \
        if(  ! null_arg(svBuf)  ) {                                     \
            if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \
            (void) SvPV_force( svBuf, na );                             \
            pBuf= (Type *) SvGROW( svBuf, sizeof(Type) );               \
            Debug(( "0x%lX==0x%lX %ld of %ld\n",                        \
              pBuf, SvPVX(svBuf), SvCUR(svBuf), SvLEN(svBuf) ));        \
        }                                                               \
    } while( FALSE )

For the XS interface shown above, you'd have:

    CODE:
        grow_buf_typ( outarg1,ST(3), struct one );
        grow_buf_typ( outarg2,ST(4), struct two );
        grow_buf_typ( outarg3,ST(5), struct three );
        RETVAL= func( handle, inarg1, inarg2, outarg1, outarg2, outarg3 );

Now, for the Perl interface.  You can just call the XS interface
directly.  If you have a lot of out args, then you could do
something like:

    func( $handle, $inarg1, $inarg2, {OUTARG1=>$outarg1,OUTARG3=>$outarg3} );

    sub func
    {

        _func( $handle, $inarg1, $inarg2,
          $outargs->{OUTARG1} || [],
          $outargs->{OUTARG2} || [],
          $outargs->{OUTARG3} || [] );
    }

That's just one idea.  I hope that helps.
--
Tye McQueen    Nothing is obvious unless you are overlooking something
         http://www.metronet.com/~tye/ (scripts, links, nothing fancy)



Mon, 25 Sep 2000 03:00:00 GMT  
 
 [ 2 post ] 

 Relevant Pages 

1. module interface design

2. Module design question (use Exporter vs require Exporter)

3. program design question (while-loop)

4. general design question

5. Australian FTP site for perl4.0 - escher.gallery.cs.unsw.oz.au

6. Soliciting views on PLs in CS education

7. Design questions about fork(), pipe() and sockets

8. Hot novel by CS professor, includes perl code

9. what questions was perl designed to solve?

10. The question about debug and design

11. how to be a CS major

12. HELP: Internet Database Design questions...

 

 
Powered by phpBB® Forum Software