next up previous index
Next: Memory Management Up: Interface to Externals Previous: I/O in External

Arrays

Arrays can be used as a convenient way to pass structured C data between C and Prolog. For example, C structures can be mapped onto Prolog integer arrays and mapping of C arrays is obvious. Passing whole arrays from Prolog to C is achieved specifying the name and order of the array like for predicates, e.g.

process(ar/2)
calls the predicate process/1 and its argument is the two-dimensional array ar. The macro
Get_Array_Address(adid, address)
  can be used to obtain the address of the global array beginning from its DID. If the DID is that of an atom, the address of the global variable is returned. If the array does not exist, an exception is raised. address must be of type pword *. Thus the macro Get_Functor_Did in combination with Get_Array_Address can be used to process arrays specified as above process(ar/2).

For advanced array usage, the macro

Get_Array_Header(adid, address)
returns the address of the array header. The array header is a pword whose tag specifies the type of the array and whose value points to further information. The array type is specified as follows: The value of the array header points to a block of (arity + 1) word32's, the first one is the DID of the array functor and the following ones are its dimensions. After the dimensions the array itself is located. Since a global variable has no header, trying to apply this macro on a global variable will issue an error.

As described in chapter gif, arrays and global variables are sensitive to the module system. The macros mentioned above always access the non-local array or variable. To access the visible array or variable in a given module, the module argument is needed. The corresponding macros are

Get_Visible_Array_Header(adid, mod_val, mod_tag, address)
Get_Visible_Array_Address(adid, mod_val, mod_tag, address)

As an example, here is the source of an external predicate that prints the contents of the specified Prolog (i.e. untyped) array which must be visible in the given module:

int
p_print_array(varr, tarr, vmod, tmod)
value   varr, vmod;
type    tarr, tmod;
{
        int        size = 1;  /* number of array elements */
        pword      *p;
        word32     *dim;
        word32     wdid;
        int        arity;

        Error_If_Ref(tarr);
        if (IsAtom(tarr))                      /* a global variable */
                wdid = varr.did;
        else                                   /* an array */
        {
                Get_Functor_Did(varr, tarr, wdid);
                Get_Visible_Array_Header(wdid, vmod, tmod, p);
                if (!IsStructure(p->tag))      /* error if not prolog */
                {
                        Error(TYPE_ERROR);
                }
                dim = (word32 *) p->val.ptr;
                dim++;                        /* skip the did */
                for (arity = DidArity(wdid); arity; arity--)
                        size *= *dim++;       /* compute the size */
        }
        Get_Visible_Array_Address(wdid, vmod, tmod, p);
        for (; size; size--, p++)
        {
                Write(p->val, p->tag, Current_Output);
                Fprintf(Current_Output, " ");
        }
        Succeed;
}

Note the use of pword and word32 pointers - the array header and array elements are pword's, the dimensions are word32's.

To avoid the need of specifying a module argument on every call, it is convenient to define a tool interface using the external predicate as the tool body:

:-  external(print_array/2, p_print_array),
    tool(print_array/1, print_array/2).
The resulting predicate print_array/1 will print the array with the specified name that is visible in the module from where print_array/1 is called.



next up previous index
Next: Memory Management Up: Interface to Externals Previous: I/O in External



Micha Meier
Mon Mar 4 12:11:45 MET 1996