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.
calls the predicate process/1 and its argument is the two-dimensional array ar. The macroprocess(ar/2)
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).Get_Array_Address(adid, address)
For advanced array usage, the macro
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:Get_Array_Header(adid, address)
As described in chapter , 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:
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.:- external(print_array/2, p_print_array), tool(print_array/1, print_array/2).