|SAS Companion for the OS/2 Environment|
Because the MODULExy routine invokes an external function that works independently of the SAS System, you must supply information about the function's arguments so that the MODULExy routine can validate them and convert them, if necessary. For example, suppose you want to invoke a routine that requires an integer as an argument. Because the SAS System uses floating point values for all of its numeric arguments, the floating point value must be converted to an integer before you invoke the external routine. The MODULExy routine looks for this attribute information in an attribute table that the SASCBTBL fileref points to.
The attribute table is a sequential text file that contains descriptions of the routines that you can invoke with the MODULExy function. The function of the table is to define how the MODULExy function should interpret its supplied arguments when it is building a parameter list to pass to the called DLL routine.
The MODULExy routines locate the table by opening the file that the SASCBTBL fileref points to. If you do not define this fileref, the MODULExy routines simply call the requested DLL routine without altering the arguments.
The attribute table should contain a description for each DLL routine that you intend to call (using a ROUTINE statement) plus descriptions of each argument that is associated with that routine (using ARG statements).
|Syntax of the Attribute Table|
At any point in the
attribute table file, you can
create a comment by using an asterisk (*) as the first nonblank character
of a line or after the end of a statement (following the semicolon). You must
end the comment with a semicolon.
The syntax of the ROUTINE statement is
ROUTINE name MINARG=minarg
The following are descriptions of the ROUTINE statement attributes:
KERNEL32,GetPathin the MODULExy function call, the ROUTINE name should be
The name argument is case sensitive, and it is required for the ROUTINE statement.
FORTRAN and COBOL are call-by-address languages; C is usually call-by-value, although a specific routine might be implemented as call-by-address.
The MODULE routine does not require that all arguments use the same calling method; you can identify any exceptions by using the BYVALUE and BYADDR options in the ARG statement, described later in this section.
L2R places the arguments on the stack in reverse order, pushing the first argument first, the second argument next, and so on, so that the last argument is the first item on the stack when the external routine executes. Pascal uses this calling convention, as do some C routines.
TRANSPOSE=YES is necessary when SAS is calling a routine that is written in a language that does not use row-major order to store matrices. (For example, FORTRAN uses column-major order.)
For example, consider this matrix that has three columns and two rows:
columns 1 2 3 -------------- rows 1 | 10 11 12 2 | 13 14 15
PROC IML stores this matrix in memory sequentially as 10, 11, 12, 13, 14, 15. However, FORTRAN routines expect this matrix to be 10, 13, 11, 14, 12, 15.
The default value is NO.
You can have multiple ROUTINE statements that use the same MODULE name. You can also have duplicate ROUTINE names that reside in different DLLs.
If you do not specify the RETURNS attribute, you should invoke the routine with only the MODULE and MODULEI call routines. You get unpredictable values if you omit the RETURNS attribute and invoke the routine by using the MODULEN/MODULEIN or MODULEC/MODULEIC functions.
The ROUTINE statement must be followed by as many ARG
statements as you specified in the MAXARG= option. The ARG statements must
appear in the order that the arguments are specified within the MODULExy routines.
The syntax for each ARG statement is
|ARG argnum NUM|CHAR <INPUT|OUTPUT|UPDATE> <NOTREQD|REQUIRED> <BYADDR|BYVALUE> <FDSTART> <FORMAT=format>;|
Here are the descriptions of the ARG statement attributes:
If you specify NUM here but you pass the routine a character argument, the argument is converted by using the standard numeric informat. If you specify CHAR here but you pass the routine a numeric argument, the argument is converted by using the BEST12 informat.
You can specify OUTPUT and UPDATE only with variable arguments (that is, you cannot specify constants or expressions).
BYADDR is the default value unless CALLSEQ=BYVALUE was specified in the ROUTINE statement, in which case BYVALUE is the default. Specify BYADDR when you are using a call-by-value routine that also has arguments to be passed by address.
The FORMAT= attribute is not required, but is recommended, since format specification is the primary purpose of the ARG statements in the attribute table.
|The Importance of the Attribute Table|
Consider an example routine
xyz that expects two arguments: an
integer and a pointer. The integer is a code that indicates what action takes
place. For example, action 1 means that a 20-byte character string is written
into the area that is pointed to by the second argument, the pointer.
Now suppose that you call
xyz by using the MODULE routine but
that you also indicate in the attribute table that the receiving character
argument is only 10 characters long:
routine xyz minarg=2 maxarg=2; arg 1 input num byvalue format=ib4.; arg 2 output char format=$char10.;Regardless of the value that was given by the LENGTH statement for the second argument to MODULE, MODULE passes a pointer to a 10-byte area to the
xyzwrites 20 bytes at that location, the 10 bytes of memory that follow the string that was provided by MODULE are overwritten, causing unpredictable results:
data _null_; length x $20; call module('xyz',1,x); run;The call executes, depending on which 10 bytes were overwritten. However, this might also cause you to lose data or cause your system to fail.
Also, note that the PEEK and PEEKC functions rely on the validity of the pointers you supply. If the pointers are invalid, it is possible that the SAS System could fail. For example, this code would cause a failure:
data _null_; length c $10; /* trying to copy from address 0!!!*/ c = peekc(0,10); run;
Be sure that your pointers are valid and that they are 32-bit pointers when you use PEEK and PEEKC.
Top of Page
Copyright 1999 by SAS Institute Inc., Cary, NC, USA. All rights reserved.