External Call Example

The example in this section illustrates how to use external calls to invoke the external routine, TRANSLOGNAM, written in the C programming language. The TRANSLOGNAM routine translates a logical name. The M source file, DM.M, invokes Direct Mode. Calling TRANSLOGNAM from GT.M returns a translated logical name in a fashion similar to the $ZTRNLNM function. For information about $ZTRNLNM(), refer to the "Functions" chapter in this manual.

Procedures:

  1. Create the source files:

    TRANSLOGNAM.C

    ZCTAB.MAR (external call table source file)

    DM.M

  2. Compile the source files using the respective language compilers.

  3. Link the TRANSLOGNAM.OBJ and ZCTAB.OBJ files to the DM.OBJ file.

  4. Run the DM.EXE image to invoke Direct Mode

  5. Use an external call to translate a logical name from M.

Using any VMS editor, create the TRANSLOGNAM.C source file and insert the code illustrated in the following program.

Program TRANSLOGNAM.C:

	#include <descrip.h>
	#include <lnmdef.h>
	#include <lib$routines.h>
	#include <starlet.h>
	long translognam (struct dsc$descriptor *src, struct dsc$descriptor *dst, struct dsc$descriptor *msg)
	{
	long status;
	long attr;
	unsigned char buffer[255];
	unsigned char buffer1[255];
	short return_length;
	short return_length1;
	$DESCRIPTOR(tabnam, "LNM$FILE_DEV");
	struct
	{
	 short buffer_length;
	 short item_code;
	 unsigned char *buffer_address;
	 short *return_length_address;
	 long terminator;
	} item_list;
	attr = LNM$M_CASE_BLIND;
	item_list.buffer_length = sizeof buffer;
	item_list.item_code = LNM$_STRING;
	item_list.buffer_address = buffer;
	item_list.return_length_address = &return_length;
	item_list.terminator = 0;
	status = sys$trnlnm(&attr, &tabnam, src, 0, &item_list);
	if (status & 1)
	{
	 dst->dsc$w_length = 0;
	 dst->dsc$b_dtype = DSC$K_DTYPE_T;
	 dst->dsc$b_class = DSC$K_CLASS_D;
	 dst->dsc$a_pointer = 0;
	 status = lib$scopy_r_dx (&return_length, buffer, dst);
	}
	return_length1 = sizeof("CURRENT GLOBAL DIRECTORY") - 1;
	strcpy(buffer1,"CURRENT GLOBAL DIRECTORY");
	msg->dsc$w_length = 0;
	msg->dsc$b_dtype = DSC$K_DTYPE_T;
	msg->dsc$b_class = DSC$K_CLASS_D;
	msg->dsc$a_pointer = 0;
	status = lib$scopy_r_dx(&return_length1, buffer1, msg);
	return status;
	}
	

Create the external call table source file and insert:

	.title zctablexample
	.library "gtm$dist:gtmzcall.mlb"
	zcinit
	routinecallname=trnlnm, linkname=translognam, inputs=1, -outputs=2
	returnclass=status
	inputposition=1, mechanism=descrip tor, type=string
	outputposition=2, mechanism=descrip tor, type=string
	outputposition=3, mechanism=descriptor, type=string
	zcallfin
	.end	
	

Create the DM.M source file and insert:

	DM FOR BREAK
	

Compile the source files.

	$ MUMPS DM
	$ CC TRANSLOGNAM
	$ MACRO ZCTAB	
	
[Note]

Alternatively, you may omit the ".library" line from the external call table source file, and add

	+GTM$DIST:GTMZCALL.MLB/LIBRARY
	

to the MACRO command, above.

Link the resultant object modules.

	$ LINK DM,ZCTAB,TRANSLOGNAM
	

Run the DM.EXE image to invoke Direct Mode.

	$ RUN DM
	GTM>
	

To translate a logical name from M, use an externref:

	GTM>WRITE $&trnlnm("GTM$GBLDIR")
	MUMPS.GLD,CURRENT GLOBAL DIRECTORY
	GTM>
	

or use the $ZCALL():

	GTM>WRITE $ZC("trnlnm","GTM$GBLDIR")
	MUMPS.GLD,CURRENT GLOBAL DIRECTORY
	GTM>
	

This $ZCALL() invokes the C program TRANSLOGNAM and passes it GTM$GBLDIR. The C program returns MUMPS.GLD, which becomes the result of the $ZCALL().

Note that returned value from external routine are comma delimited string and their position depend on the relative position of the "output" specification in the external call table. If we swap the "output" specification in ZCTAB.MAR, the returned value would be:

	CURRENT GLOBAL DIRECTORY,MUMPS.GLD