[comp.lang.apl] Interfacing J

krb@math.ufl.edu (Ken Block) (04/18/91)

Can J be interfaced to other languages? I would like to do graphics and
have more control over files. Presently to display images I am writing
them to a file and then invoking Xloadimage with 0!:0.

BTW, I am very happy to see a sun3 version is back out. The majority
of our machines are still sun3s.

sam@gabriel.jpl.nasa.gov (Sam Sirlin) (04/18/91)

In article <1991Apr17.202320.13658@math.ufl.edu>, krb@math.ufl.edu (Ken Block) writes:
|> Can J be interfaced to other languages? I would like to do graphics and

One can do graphics directly in J. I translated some old tektronix ploting 
functions I had into J. They work fine (under Xwindows) with minor 
modifications to pop up an Xterm tektronix window. The actual drawing is 
pretty fast (sparc 1), though the calculations seem to take a long time.

-- 
Sam Sirlin
Jet Propulsion Laboratory         sam@kalessin.jpl.nasa.gov

hui@yrloc.ipsa.reuter.COM (Roger Hui) (04/19/91)

You have Professor L.J. Dickey to thank for the updated J/Sun3.

The product described below is currently in beta test.  It will be
available soon, sooner on some machines than others.  I should point
out that we have not yet decided whether or not it'd be shareware,
or how much it'd cost.
--------------------------------------------------------------

LinkJ
 
Roger Hui
1991 3 31
 
 
J is a dialect of APL specified by "A Dictionary of J".  LinkJ is a set of
object modules which together offer the full capability of J while allowing
links to other compiled routines and libraries.  It is possible to call
LinkJ from C and to call C from LinkJ.
 
The interface consists of the following definitions and functions.
 
  typedef char C;                      C jinit(void);
  typedef long I;                      A jx(C*s);
  typedef struct{I t,c,n,r,*s;}*A;     A jpr(A x);
  typedef A (*AF)();                   A jma(I t,I n,I r);
                                       C jfr(A x);
  C jerr;                              A jset(C*name,A x);
                                       C jc(I k,AF*f1,AF*f2);
 
"A" is the type of an array.  The parts are the type, an internal reference
count, the number of elements in the array, the rank, the shape, and the
array elements, in a contiguous segment of memory.  (Array types are boolean,
literal, integer, floating point, complex, and boxed.  See file lj.h.)
AF typifies a function which accepts one or more array arguments, and returns
an array result; i.e. AF is the type of a verb.
 
jinit() initializes J.  The result is 1 if the operation is successful, and 0
if not.  jx() takes a 0-terminated string argument representing a sentence,
and returns the array result of executing the sentence.  For example,
   jinit();
   p=jx("a=.i.3 4\0");
   q=jx("+/,a\0");
p is a 3 by 4 matrix of the integers from 0 to 11, and q is the atom 66.
The space occupied by the array result of jx() is reused the next time
jx() is called.
 
Therefore, jinit() and jx() by themselves offer the full capabilities
of J.  The other functions provide a more convenient and efficient interface.
 
jpr(x) prints array x on the standard output.  The result is x itself.
 
jma(t,n,r) allocates memory for an array of type t, having n elements and
rank r; you are then responsible for filling in the shape and the elements.
jfr() frees an array previously allocated by jma().  Array arguments and
results must use space managed by jma() and jfr().
 
jset(name,x) assigns a value to a global name (as in the copula =:).  name is
a 0-terminated string; x is an array.  The result of jset() is x itself.
jx(name) returns the referent of a name.
 
The preceding functions allow calling J from C.  Here, we describe how to
call C from J.  A new case of the !: external conjunction is defined:  10!:k
is a verb whose definition is controlled by jc(), a C function you write
yourself, as follows:
 
C jc(I k,AF*f1,AF*f2){
 switch(k){
 /* k:  index                               */
 /* f1: pointer to monad (NULL if no monad) */
 /* f2: pointer to dyad  (NULL if no dyad ) */
 /* function result is zero if there is an error, nonzero if no error */
}}
 
10!:k invokes jc(k,&f1,&f2), wherein (presumably depending on k) you assign
to *f1 a pointer to a monadic function and to *f2 a pointer to a dyadic
function.  The result of 10!:k is a verb like any other; in particular, it
may be assigned a name and (orthogonally) may serve as argument to adverbs
and conjunction such as prefix and rank; and when it is invoked with
arguments the functions you assigned to *f1 and *f2 will be invoked with
those arguments.
 
When an error is encountered in an interface function, the result is 0
(if the result type is C) or NULL (if the result type is A), and the global
variable jerr contains an error number.  Error numbers are defined in file
lj.h.
 
File main.c contains an example of using LinkJ.  It has a main() function
which does, ad infinitum:
 - get a line of input from the terminal;
 - execute the line;
 - print the result (or the error number).
(To terminate, enter ")off".)  As well, main.c has an example of using jc(),
whereby  10!:0 y  computes  #,y , the number of elements in array y; and
x 10!:0 y  computes  x{.,y , the first x elements of integer array y.
 
C compilation procedures differ from system to system, so the procedure for
using LinkJ is necessarily system dependent.  On the IBM PC, in the TurboC
Integrated Development Environment:
  a) Put the names of all the LinkJ object modules in the project file.
  b) Put the names of your own C source files ("main" in the current example)
     into the project file.
  c) Select the Make option.
Under UNIX, enter:  cc main.c linkj/*.o -o test  .
 
 
Acknowledgement.  Paul Chapman described the design of 10!:k and jc()
to me on December 12, 1990, during his Toronto visit.

----------------------------------------------------------------

Roger Hui
Iverson Software Inc., 33 Major Street, Toronto, Ontario  M5S 2K9
(416) 925 6096