Examples of Accessing Shared Executable Libraries From SAS


Example 1: Updating a Character String Argument

This example uses the tmpnam routine in the Solaris supplied shared library libc.so installed in the /usr/lib/sparcv9 directory. The tmpnam routine generates a unique filename that can be used safely as a temporary filename. The temporary filename is typically placed in the /var/tmp directory.

The C prototype for this routine is:

 char * tmpnam(char *s); 

The attribute table for this would be:

 routine tmpnam minarg=1 maxarg=1 returns=char255. module=libc;   arg 1 char output byaddr format=$cstr255; 

The SAS source code would be:

 x 'if [ ! -L ./libc ] ; then ln -s /usr/lib/sparcv9/libc.so.1 ./libc ; fi' ;   x 'setenv LD_LIBRARY_PATH .:/usr/lib/sparcv9:/usr/lib:/lib';   data _null_;      length tempname 5 tname 5;      retain tempname tname '' '';      tname = modulec ('tmpnam', tempname);      put tempname = ;      put tname = ;   run; 

The SAS log output would be:

Output 7.4: Updating a Character String Argument
start example
 tempname=/var/tmp/aaaKraydG tname=/var/tmp/aaaKraydG 
end example
 

The POSIX standard for the maximum number of characters in a pathname is defined in /usr/include/limits.h to be 255 characters, so this example uses 254 as the length of the generated filename ( tempname ) with one character reserved for the null terminator. The $CSTR255. informat ensures that the null-terminator and all subsequent characters are replaced by trailing blanks when control returns to the DATA step.

Example 2: Passing Arguments by Value

This example calls the access routine that is supplied by most UNIX vendors . This particular access routine is in the Hewlett Packard shared library libc.sl installed under the /usr/lib/pa20_64 directory.

The C prototype for this routine is:

 int access(char *path, int amode); 

The access routine checks the file that is referenced by the accessibility path according to the bit pattern contained in amode . You can use the following integer values for amode that correspond to the type of permission for which you are testing:

 4    Read access   2    Write access   1    Execute (search) access   0    Check existence of file 

A return value of 0 indicates a successful completion and the requested access is permitted. A return value of -1 indicates a failure and the requested access is not permitted.

Because the amode argument is a pass by value, this example includes the BYVALUE specification for the arg 2 in the attribute table. If both arguments were pass by value, one could use the CALLSEQ=BYVALUE attribute in the ROUTINE statement and it would not be necessary to specify the BYVALUE option in arg 2.

The attribute table would be:

 routine access minarg=2 maxarg=2 returns=short module=libc;   arg 1 char input byaddr format=$cstr200.;   arg 2 num input byvalue format=ib4.; 

The SAS source code would be:

 x 'if [ ! -L ./libc ] ; then ln -s /usr/lib/pa20_64/libc.so ; fi' ;   x 'setenv LD_LIBRARY_PATH .:/usr/lib/pa20_64:/usr/lib:/lib' ;   data _null_;     length path 0.;     path='/dev';     /* A non-root user is testing for write permission in the /dev directory */     rc = modulen("*ie",'access',path,2);     put rc = ;   run; 

The SAS log output would be:

Output 7.5: Log Output If Request Access Is Permitted
start example
 rc=-1 
end example
 

If you changed the SAS source code to check for a write permission in the user's $HOME directory, the output would be different.

 data _null_;      length homedir 0.;      homedir=sysget('HOME');      /* A user is testing for write permissions in their $HOME directory */      rc = modulen(''*ie'','access',homedir,2);      put rc = ;   run; 

In this case, the SAS log output would be:

Output 7.6: Log Output for Successful Completion (Access Permitted)
start example
 rc=0 
end example
 

Example 3: Using PEEKCLONG to Access a Returned Pointer

This example uses the strcat routine which is part of the Red Hat Linux shared library libc-2.2.3.so. This library is typically installed under the /lib/i686 directory. This routine concatenates two strings together and returns a pointer to the newly concatenated string.

The C prototype for this routine is:

 char *strcat(char, *dest, const char *src); 

The proper SASCBTBL attribute table would be:

 routine strcat minarg=2 maxarg=2 returns=ulong module=libc;   arg 1 char input format=$cstr200.;   arg 2 char input format=$cstr200.; 

The SAS code would be:

 x 'if [ ! -L ./libc ]; then ln -s /lib/i686/libc-2.2.3.so ./libc ; fi' ;   x 'setenv LD_LIBRARY_PATH .:/lib/i686:/usr/lib:/lib';   data _null_;      length string1 string2 newstring 0;      string1 = 'This is string one and';      string2 = 'this is string two.' ;      ptraddr = modulen('strcat',string1,string2);      newstring = peekclong(ptraddr,200);      put newstring = ;   run; 

The SAS log output would be:

Output 7.7: Log Output for Using PEEKCLONG to Access a Returned Pointer
start example
 newstring=This is string one and this is string two. 
end example
 

The PEEKCLONG function was used here because the Red Hat Linux shared library /lib/i686/libc-2.2.3.so is a 32-bit library. The following output demonstrates this:

 $pwd   /lib/i686   $file ./libc-2.2.3.so   libc-2.2.3.so: ELF 32-bit LSB shared object, Intel 80386, version 1, not stripped 

For more information about the PEEKLONG functions, see "PEEKLONG Function" on page 254.

Example 4: Using Structures

"Grouping SAS Variables as Structure Arguments" on page 179 describes how to use the FDSTART attribute to pass several arguments as one structure argument to a shared library routine. This is another example of using structures with another routine in an external shared library.

The statvfs routine that is available under most UNIX operating systems retrieves file system information. This example uses the statvfs routine that is in the Solaris libc.so.1 shared library and typically installed under the /usr/lib/sparcv9 directory.

The C prototype for this routine is:

 int statvfs(const char *path, struct statvfs *buf); 

The statvfs routine will return a 0 if the routine completes successfully and -1 if there is a failure.

The statvfs structure is defined with the following members :

 unsigned long f_bsize;            /* preferred file system block size */   unsigned long f_frsize;           /* fundamental file system block */   unsigned long f_blocks;           /* total number of lbocks on file system in units */   unsigned long f_bfree;            /* total number of free blocks */   unsigned long f_bavail;           /* number of free blocks available to non-superuser */   unsigned long f_files;         /* total number of file nodes (inodes) */   unsigned long f_ffree;         /* total number of free file nodes */   unsigned long f_favail;        /* number of inodes available to non-superuser */   unsigned long f_fsid;          /* file system id (dev for now) */   char          f_basetype[16];  /* target fs type name, null-terminated */   unsigned long f_flag;          /* bit mask of flags */   unsigned long g f_namemax;     /* maximum filename length */   char          f_fstr[32];      /* file system specific string */ 

The SASCBTBL attribute table would be:

 routine statvfs      minarg=14      maxarg=14      returns=short      module=libc;   arg 1  char input  byaddr         format=$char256.;   arg 2  num  output byaddr fdstart format=pib8.;   arg 3  num  output                format=pib8.;   arg 4  num  output                format=pib8.;   arg 5  num  output                format=pib8.;   arg 6  num  output                format=pib8.;   arg 7  num  output                format=pib8.;   arg 8  num  output                format=pib8.;   arg 9  num  output                format=pib8.;   arg 10 num  output                format=pib8.;   arg 11 char output                format=$cstr16.;   arg 12 num  output                format=pib8.;   arg 13 num  output                format=pib8.;   arg 14 char output                format=$cstr32.; 

The SAS source code to call the statvfs routine from within the DATA step would be:

 x 'if [ ! -L ./libc ]; then ln -s /usr/lib/sparcv9/libc.so.1 ./libc ; fi' ;   x 'setenv LD_LIBRARY_PATH .:/usr/lib/sparcv9:/usr/lib:/lib';   data _null_;      length f_basetype . f_fstr .;      retain f_bsize f_frsize f_blocks f_bfree f_bavail f_files f_ffree f_favail             f_fsid f_flag f_namemax 0;      retain f_basetype f_fstr ' ';      rc=modulen ('statvfs' , '/tmp', f_bsize, f_frsize, f_blocks, f_bfree, f_bavail,                  f_files, f_ffree, f_favail, f_fsid, f_basetype, f_flag,                  f_namemax, f_fstr);      put rc = ;      put f_bsize = ;      put f_frsize = ;      put f_blocks = ;      put f_bfree = ;      put f_bavail = ;      put f_files = ;      put f_ffree = ;      put f_favail = ;      put f_fsid = ;      put f_basetype = ;      put f_flag = ;      put f_namemax = ;      /* Determining the total bytes available in the file system and then dividing the      total number of bytes by the number of bytes in a gigabyte */      gigsfree = ((f_bavail * f_bsize)/1073741824);      put 'The total amount of space available in /tmp is 'gigsfree 4.2' Gigabytes.';   run; 

The SAS log output would be:

Output 7.8: Log Output for Using Structures
start example
 rc=0 f_bsize=8192 f_frsize=8192 f_blocks=196608 f_bfree=173020 f_bavail=173020 f_files=884732 f_ffree=877184 f_favail=877184 f_fsid=2 f_basetype=tmpfs f_flag=4 f_namemax=255 The total amount of space available in /tmp is 1.32 Gigabytes. 
end example
 

Example 5: Invoking a Shared Library Routine From PROC IML

This example shows how to pass a matrix as an argument within PROC IML. The example creates a 4x5 matrix. Each cell is set to 10 x + y +3, where x is the row number and y is the column number. For example, the cell at row 1 column 2 is set to (10*1)+2+3, or 15.

The example invokes several routines from the theoretical TRYMOD shared library. It uses the changd routine to add 100 x +10 y to each element, where x is the C row number (0 through 3) and y is the C column number (0 through 4). The first argument to changd specifies the extra amount to sum. The changdx routine works just like changd , except that it expects a transposed matrix. The changi routine works like changd except that it expects a matrix of integers. The changix routine works like changdx except that integers are expected.

Note  

A maximum of three arguments can be sent when invoking a shared library routine from PROC IML.

In this example, all four matrices x1, x2, y1, and y2 should become set to the same values after their respective MODULEIN calls. Here are the attribute table entries:

 routine changd module=trymod returns=long;   arg 1 input num format=rb8. byvalue;   arg 2 update num format=rb8.;   routine changdx module=trymod returns=long      transpose=yes;   arg 1 input num format=rb8. byvalue;   arg 2 update num format=rb8.;   routine changi module=trymod returns=long;   arg 1 input num format=ib4. byvalue;   arg 2 update num format=ib4.;   routine changix module=trymod returns=long      transpose=yes;   arg 1 input num format=ib4. byvalue;   arg 2 update num format=ib4.; 

Here is the PROC IML step:

 proc iml; x1 = J(4,5,0);     do i=1 to 4;        do j=1 to 5;           x1[i,j] = i*10+j+3;           end;     end;     y1= x1; x2 = x1; y2 = y1;     rc = modulein('changd',6,x1);     rc = modulein('changdx',6,x2);     rc = modulein('changi',6,y1);     rc = modulein('changix',6,y2);     print x1 x2 y1 y2;   run; 

The following are the results of the PRINT statement:

Output 7.9: Invoking a Shared Library Routine from PROC IML
start example
 X1  20       31       42       53       64 130      141      152      163      174 240      251      262      273      284 350      361      372      383      394  X2  20       31       42       53       64 130      141      152      163      174 240      251      262      273      284 350      361      372      383      394  Y1  20       31       42       53       64 130      141      152      163      174 240      251      262      273      284 350      361      372      383      394  Y2  20       31       42       53       64 130      141      152      163      174 240      251      262      273      284 350      361      372      383      394 
end example
 



SAS 9.1 Companion for UNIX Environments
SAS 9.1 Companion For Unix Enivronments
ISBN: 1590472101
EAN: 2147483647
Year: 2004
Pages: 185
Authors: SAS Institute

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net