[Date Prev] [Date Next] [Thread Prev] [Thread Next] Date Index Thread Index Search archive:
Date:Mon May 4 11:32:27 1994 
Subject:Re: calling external functions with a structure 
From:Adrian John Howard 
Volume-ID:940504.02 

[David said]
> I am trying to externally load a function, tcgetattr actually.
> The type for this is:
>
> int tcgetattr(int, struct termios *);
>
> How should I accomplish this in pop11 ?
>
> So far I have set up a p_typespec for the termios struct.
> But cannot seem to easily specify that I want a ptr to that struct as
> the second argument.
>

"And verily it was said, many and wonderful are the ways of accessing
the world external in Pop-11"... and here are a few of them:

Ok. We have your p_typespec for the -termios- structure

    p_typespec termios {
        c_iflag :long,
        c_oflag :long,
        c_lflag :long,
        c_cc    :byte[19]
    };

or whatever.

From Poplog V14.5 you can use the "exptr_mem" external pointer class
(see REF * EXTERNAL_DATA) so:

    vars t_ptr = initexptr_mem(SIZEOFTYPE(:termios))

which can be stated more succinctly with the -EXPTRINITSTR- macro (see
REF * DEFSTRUCT)

    vars t_ptr = EXPTRINITSTR(:termios);

These just create pointers to a fixed-address chunk of memory of the
specified size. You can use optional arguments to specify whether the
memory should be garbage collected just like you can with -cons_fixed-.

Alternatively, you can just pass any Poplog vector class wrapped up as an
external pointer --- as long as you're willing to be careful with GC:-)

    vars t_ptr =
        exptr_init_fixed(SIZEOFTYPE(:termios, :int), intvec_key);

You can pass optional arguments to create fixed-address structures if
necessary (before "exptr_mem" structures, -EXPTRINITSTR- used to work
like this.)

In either of these case you would do something like this:

    exload 'tcgetattr'
        (language C)
        raw_tcgetattr(int, termios) :int <- tcgetattr;
    endexload;

    vars err=exacc raw_tcgetattr(poprawdevout.device_os_channel, t_ptr);
    err=>
    ** 0

    exacc :termios t_ptr.c_iflag=>
    ** 11526

If you would like to access the pointer like a Pop-11 structure you can
use LIB * SHADOWCLASS. This allows you to create a Pop-11 "shadow" of an
external structure. For example, the following

    uses shadowclass;
    shadowclass termiosP :termios;

will create the following procedures

    istermiosP(item) -> bool
    inittermiosP() -> termiosP
    constermiosP(iflag, oflag, lflag, cc) -> termiosP
    desttermiosP(termiosP) -> (iflag, oflag, lflag, cc)
    filltermiosP(iflag, oflag, lflag, cc, termiosP) -> termiosP

which have there normal Pop-11 meanings. It will also create the
following field access procedures

    c_iflag(termiosP) -> long
    c_oflag(termiosP) -> long
    c_lflag(termiosP) -> long
    c_cc(termiosP) -> vec

along with two special procedures;

    importtermiosP(exptr) -> termiosP
        Which will take an external pointer to a termios structure, and
        return the shadowclass equivalent.

    refreshtermiosP(termiosP) -> termiosP
        Which refreshes the Pop-11 shadow of the external structure.

It also creates the special "shadow key" structure

    termiosP_shadowkey

Despite all this, it's dead easy to use:

    define tcgetattr(dev, termiosP) -> int;
        lvars dev, termiosP, int;
        exacc raw_tcgetattr(dev.device_os_channel, termiosP) -> int;
        ;;; EXTERNAL STRUCTURE CHANGED SO WE NEED TO REFRESH SHADOW
        refreshtermiosP(termiosP) ->;
    enddefine;

    vars t_ptr=inittermiosP();
    t_ptr=>
    ** <termiosP 0 0 0 {0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}>

    tcgetattr(poprawdevout, t_ptr)=>
    ** 0

    t_ptr=>
    ** <termiosP 11526 5 189 {0 0 138 59 3 28 127 21 4 0 0 0 17 19 26 25 18 15 23}>

    t_ptr.c_iflag=>
    ** 11526

Obviously, the ease of use has efficiency drawbacks (that Pop-11 shadow
takes time and space to maintain.) For full details see REF *
SHADOWCLASS.

Hope this makes some sense :-)

aids (adrianh@cogs.susx.ac.uk)  ObDisclamer: Poplog used to pay my wages
Phone: +44 (0)273 678367  URL: http://www.cogs.susx.ac.uk/users/adrianh/