Examples


Updating a Character String Argument

This example uses the Win32 routine GetTempPathA. This routine expects as an argument a pointer to a buffer, along with the length of the buffer. GetTempPathA fills the buffer with a null- terminated string representing the temporary path . Here is the C prototype for the GetTempPathA routine:

 DWORD WINAPI GetTempPathA      (DWORD nBufferLength, LPSTR lpBuffer); 

Here is the attribute table:

 routine GetTempPathA    minarg=2    maxarg=2    stackpop=called    returns=long;  arg 1 input  byvalue format=pib4.;  arg 2 update         format=$cstr200.; 

Note that the STACKPOP=CALLED option is used; all Win32 service routines require this attribute. The first argument is passed by value because it is an input argument only. The second argument is an update argument because the contents of the buffer are to be updated. The $CSTR200. format allows for a 200-byte character string that is null-terminated.

Here is the SAS code to invoke the function. In this example, the DLL name (KERNEL32) is explicitly given in the call (because the MODULE attribute was not used in the attribute file):

 filename sascbtbl "sascbtbl.dat";  data _null_;    length path 0;    n = modulen( '*i',        "KERNEL32,GetTempPathA", 199, path );    put n= path=;  run; 

Note: KERNEL32.DLL is an internal DLL provided by Windows. Its routines are described in the Microsoft Win32 SDK.

The code produces these log messages:

 NOTE: Variable PATH is uninitialized.  N=7 PATH=C:\TEMP 

The example uses 199 as the buffer length because PATH can hold up to 200 characters with one character reserved for the null terminator. The $CSTR200. informat ensures that the null-terminator and all subsequent characters are replaced by trailing blanks when control returns to the DATA step.

Passing Arguments by Value

This example calls the Beep routine, part of the Win32 API in the KERNEL32 DLL. Here is the C prototype for Beep:

 BOOL Beep(DWORD dwFreq, DWORD dwDuration) 

Here is the attribute table to use:

 routine Beep    minarg=2    maxarg=2    stackpop=called    callseq=byvalue    module=kernel32;  arg 1 num format=pib4.;  arg 2 num format=pib4.; 

Because both arguments are passed by value, the example includes the CALLSEQ=BYVALUE attribute in the ROUTINE statement, so it is not necessary to specify the BYVALUE option in each ARG statement.

Here is the sample SAS code used to call the Beep function:

 filename sascbtbl 'sascbtbl.dat';  data _null_;    rc = modulen("*e","Beep",1380,1000);  run; 

The computer speaker beeps.

Using PEEKCLONG to Access a Returned Pointer

The following example uses the lstrcat routine, part of the Win32 API in KERNEL32.DLL. lstrcat accepts two strings as arguments, concatenates them, and returns a pointer to the concatenated string. The C prototype is

 LPTSTR lstrcat (LPTSTR lpszString1,                  LPCTSTR lpszString2); 

The following is the proper attribute table:

 routine lstrcat    minarg=2    maxarg=2    stackpop=called    module=KERNEL32    returns=ulong;    arg 1 char format=$cstr200.;    arg 2 char format=$cstr200.; 

To use lstrcat , you need to use the SAS PEEKCLONG function to access the data referenced by the returned pointer. Here is the sample SAS program that accesses lstrcat :

 filename sascbtbl 'sascbtbl.dat';  data _null_;    length string1 string2 conctstr 0;    string1 = 'This is';    string2 = ' a test!';    rc = modulen('lstrcat',string1,string2);    conctstr = peekclong(rc,200);    put conctstr=;  run; 

The following output appears in the log:

 conctstr=This is a test! 

Upon return from MODULEN, the pointer value is stored in RC. The example uses the PEEKCLONG function to return the 200 bytes at that location, using the $CSTR200. format to produce a blank- padded string that replaces the null termination.

For more information about the PEEKLONG functions, see the PEEKCLONG function and the PEEKLONG function in SAS Language Reference: Dictionary .

Using Structures

Grouping SAS Variables as Structure Arguments on page 303 describes how to use the FDSTART attribute to pass several arguments as one structure argument to a DLL routine. Refer to that section for an example of the GetClientRect attribute table and C language equivalent. This example shows how to invoke the GetClientRect function after defining the attribute table.

The most straightforward method works, but generates a warning message about the variables not being initialized :

 filename sascbtbl 'sascbtbl.dat';  data _null_;       hwnd=modulen('GetForegroundWindow');       call module('GetClientRect',hwnd,         left,top,right,bottom);       put _all_;       run; 

To remove the warning, you can use the RETAIN statement to initialize the variables to 0. Also, you can use shorthand to specify the variable list in the MODULEN statement:

 data _null_;       retain left top right bottom 0;       hwnd=modulen('GetForegroundWindow');       call module('GetClientRect',hwnd,             of left--bottom);       put _all_;       run; 

Note that the OF keyword indicates that what follows is a list of variables, in this case delimited by the double-dash. The output in the log varies depending on the active window and looks something like the following:

 HWND=3536768 LEFT=2 TOP=2 RIGHT=400  BOTTOM=587 

Invoking a DLL 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 DLL. 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 indicates what 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 DLL 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:

 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 



SAS 9.1 Companion for Windows
SAS 9.1 Companion for Windows (2 Volumes)
ISBN: 1590472004
EAN: 2147483647
Year: 2004
Pages: 187

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