open pdf in webbrowser control c# : Delete text pdf software Library dll winforms .net asp.net web forms hostwin31-part233

Chapter 13
Accessing External DLLs from 
SAS under Windows
Overview of Dynamic Link Libraries in SAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
The SASCBTBL Attribute Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
Overview of the SASCBTBL Attribute Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
Syntax of the Attribute Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
The Importance of the Attribute Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Special Considerations When Using External DLLs . . . . . . . . . . . . . . . . . . . . . . . . 297
Using PEEKLONG Functions to Access Character String Arguments . . . . . . . . . 297
Accessing External DLLs Efficiently . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
Grouping SAS Variables as Structure Arguments . . . . . . . . . . . . . . . . . . . . . . . . . 299
Using Constants and Expressions as Arguments to MODULE . . . . . . . . . . . . . . . 300
Specifying Formats and Informats to Use with MODULE Arguments . . . . . . . . . 301
Understanding MODULE Log Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
Updating a Character String Argument . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
Passing Arguments by Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
Using PEEKCLONG to Access a Returned Pointer . . . . . . . . . . . . . . . . . . . . . . . . 308
Using Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
Invoking a DLL Routine from PROC IML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
Overview of Dynamic Link Libraries in SAS
Dynamic link libraries (DLLs) are executable files that contain one or more routines 
written in any of several programming languages. DLLs are a mechanism for storing 
useful routines that might be needed by many applications. When an application needs a 
routine that resides in a DLL, it loads the DLL, invokes the routine, and unloads the 
DLL upon completion. SAS provides routines and functions that let you invoke these 
external routines from within SAS. You can access the DLL routines from the DATA 
step, the IML procedure, and SCL code. You use the MODULE family of SAS call 
routines and functions (including MODULE, MODULEN, MODULEC, MODULEI, 
MODULEIN, and MODULEIC) to invoke a routine that resides in an external DLL. 
This documentation refers to the MODULE family of call routines and functions 
generically as the MODULE functions.
These are general steps for accessing an external DLL routine:
1. Create a text file that describes the DLL routine that you want to access, including 
the arguments that it expects and the values that it returns (if any). This attribute file 
291
Delete text pdf - delete, remove text from PDF file in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Allow C# developers to use mature APIs to delete and remove text content from PDF document
how to delete text in pdf document; pdf text watermark remover
Delete text pdf - VB.NET PDF delete text library: delete, remove text from PDF file in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
VB.NET Programming Guide to Delete Text from PDF File
how to delete text in pdf using acrobat professional; how to erase in pdf text
must be in a special format, as described in “The SASCBTBL Attribute Table” on 
page 292 . 
2. Use the FILENAME statement to assign the SASCBTBL fileref to the attribute file 
that you created.
3. In a DATA step or SCL code, use a call routine or function (MODULE, MODULEN, 
or MODULEC) to invoke the DLL routine. The specific function that you use 
depends on the type of expected return value (none, numeric, or character). (You can 
also use MODULEI, MODULEIN, or MODULEIC within a PROC IML step.) The 
MODULE functions are described in “MODULE Function: Windows” on page 
411 . 
CAUTION:
Only experienced programmers should access external DLLs.
By accessing a 
function in an external DLL, you transfer processing control to the external function. 
If done improperly, or if the external function is not reliable, you might lose data or 
have to reset your computer (or both).
The SASCBTBL Attribute Table
Overview of the SASCBTBL Attribute Table
Because the MODULE routine invokes an external function that SAS knows nothing 
about, you must supply information about the function's arguments so that the MODULE 
routine can validate them and convert them. For example, suppose you want to invoke a 
routine that requires an integer as an argument. Because SAS 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 MODULE routine looks for this attribute 
information in an attribute table referred to by the SASCBTBL fileref.
The attribute table is a sequential text file that contains descriptions of the routines that 
you can invoke with the MODULE function. The function of the table is to define how 
the MODULE function should interpret its supplied arguments when building a 
parameter list to pass to the called DLL routine.
The MODULE routines locate the table by opening the file referred to by the 
SASCBTBL fileref. If you do not define this fileref, the MODULE routines simply call 
the requested DLL routine without altering the arguments.
CAUTION:
Using the MODULE functions without defining an attribute table can cause SAS 
to crash or force you to reset your computer.
You need to use an attribute table 
for all external functions that you want to invoke.
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 associated with 
the routine (using ARG statements).
292
Chapter 13 • Accessing External DLLs from SAS under Windows
VB.NET PDF Page Delete Library: remove PDF pages in vb.net, ASP.
›› VB.NET PDF: Delete PDF Page. VB.NET PDF - How to Delete PDF Document Page in VB.NET. Visual Basic Sample Codes to Delete PDF Document Page in VB.NET Class.
how to delete text in pdf file online; how to delete text from pdf with acrobat
C# PDF Page Delete Library: remove PDF pages in C#.net, ASP.NET
Page: Delete Existing PDF Pages. |. Home ›› XDoc.PDF ›› C# PDF: Delete PDF Page. C#.NET PDF Library - Delete PDF Document Page in C#.NET.
delete text pdf document; remove text watermark from pdf
Syntax of the Attribute Table
Overview of the Syntax of the Attribute Table
At any point in the attribute table file, you can create a comment 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.
ROUTINE Statement
The following is the syntax of the ROUTINE statement:
ROUTINE name MINARG=minarg MAXARG=maxarg
<CALLSEQ=BYVALUE|BYADDR>
<STACKORDER=R2L|L2R>
<STACKPOP=CALLER|CALLED>
<TRANSPOSE=YES|NO> <MODULE=DLL-name>
<RETURNS=SHORT|USHORT|LONG|INT64|ULONG |DOUBLE|DBLPTR|CHAR<n>>
<RETURNREGS=DXAX>;
The following are descriptions of the ROUTINE statement attributes:
ROUTINE name
starts the ROUTINE statement. You need a ROUTINE statement for every DLL 
function that you intend to call using the MODULE function. The value for name 
must match the routine name or ordinal that you specified as part of the 'module' 
argument in the MODULE function, where module is the name of the DLL (if not 
specified by the MODULE attribute, described later) and the routine name or 
ordinal. For example, to be able to specify KERNEL32,GetPath in the MODULE 
function call, the ROUTINE name should be GetPath.
The name argument is case sensitive, and is required for the ROUTINE statement.
MINARG=minarg
specifies the minimum number of arguments to expect for the DLL routine. In most 
cases, this value is the same as MAXARG; but some routines do allow a varying 
number of arguments. This is a required attribute.
MAXARG=maxarg
specifies the maximum number of arguments to expect for the DLL routine. This is a 
required attribute.
CALLSEQ=BYVALUE | BYADDR
indicates the calling sequence method used by the DLL routine. Specify BYVALUE 
for call-by-value and BYADDR for call-by-address. The default value is BYADDR.
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.
STACKORDER=R2L | L2R
indicates the order of arguments on the stack as expected by the DLL routine. R2L 
places the arguments on the stack according to C language conventions. The last 
argument (right-most in the call syntax) is pushed first, the next-to-last argument is 
The SASCBTBL Attribute Table
293
VB.NET PDF Text Extract Library: extract text content from PDF
PDF ›› VB.NET PDF: Extract PDF Text. VB.NET PDF - Extract Text from PDF Using VB. How to Extract Text from PDF with VB.NET Sample Codes in .NET Application.
how to delete text in a pdf acrobat; delete text pdf acrobat professional
C# PDF Text Extract Library: extract text content from PDF file in
XDoc.PDF ›› C# PDF: Extract PDF Text. C# PDF - Extract Text from PDF in C#.NET. Feel Free to Extract Text from PDF Page, Page Region or the Whole PDF File.
remove text from pdf online; how to delete text from a pdf document
pushed next, and so on, so that the first argument is the first item on the stack when 
the external routine takes over. R2L is the default value.
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 takes over. Pascal uses this calling convention, 
as do some C routines.
STACKPOP=CALLER | CALLED
specifies which routine, the caller routine or the called routine, is responsible for 
popping the stack (updating the stack pointer) upon return from the routine. The 
default value is CALLER (the code that calls the routine). Some routines that use 
Microsofts __stdcall attribute with 32-bit compilers, require the called routine to pop 
the stack.
TRANSPOSE=YES | NO
specifies whether to transpose matrices with both more than one row and more than 
one column before calling the DLL routine. This attribute applies only to routines 
called from within PROC IML with MODULEI, MODULEIC, and MODULEIN.
TRANSPOSE=YES is necessary when calling a routine 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 with 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 as 10, 13, 11, 14, 12, 15.
The default value is NO.
MODULE=DLL-name
names the executable module (the DLL) in which the routine resides. The MODULE 
function searches the directories named by the PATH environment variable. If you 
specify the MODULE attribute here in the ROUTINE statement, then you do not 
need to include the module name in the module argument to the MODULE function 
(unless the DLL routine name that you are calling is not unique in the attribute 
table). The MODULE function is described in “MODULE Function: Windows” on 
page 411 .
You can have multiple ROUTINE statements that use the same MODULE name. 
You can also have duplicate ROUTINE names that reside in different DLLs.
RETURNS=SHORT | USHORT | LONG | INT64 | ULONG | DOUBLE | DBLPTR | 
CHAR<n>
specifies the type of value that the DLL routine returns. This value is converted as 
appropriate, depending on whether you use MODULEC (which returns a character) 
or MODULEN (which returns a number). The possible return value types are
SHORT
short integer
USHORT
unsigned short integer
LONG
long integer
ULONG
unsigned long integer
294
Chapter 13 • Accessing External DLLs from SAS under Windows
C# PDF insert text Library: insert text into PDF content in C#.net
Text to PDF. C#.NET PDF SDK - Insert Text to PDF Document in C#.NET. Providing C# Demo Code for Adding and Inserting Text to PDF File Page with .NET PDF Library.
delete text pdf file; how to erase text in pdf online
C# PDF Convert to Text SDK: Convert PDF to txt files in C#.net
C#.NET PDF SDK - Convert PDF to Text in C#.NET. Integrate following RasterEdge C#.NET text to PDF converter SDK dlls into your C#.NET project assemblies;
delete text pdf files; pdf editor online delete text
INT64
long long integer
DOUBLE
double-precision floating point number
DBLPTR
a pointer to a double-precision floating point number (instead of using a floating 
point register). Consult the documentation for your DLL routine to determine 
how it handles double-precision floating-point values.
CHARn
pointer to a character string up to n bytes long. The string is expected to be null-
terminated and is blank-padded or truncated as appropriate. If you do not specify 
n, the MODULE function uses the maximum length of the receiving SAS 
character variable.
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 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 in 
which the arguments are specified within the MODULE routines.
ARG Statement
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:
ARG argnum
defines the argument number. This attribute is required. Define the arguments in 
ascending order, starting with the first routine argument (ARG 1).
NUM | CHAR
defines the argument as numeric or character. This attribute is required.
If you specify NUM here but pass the routine a character argument, the argument is 
converted using the standard numeric informat. If you specify CHAR here but pass 
the routine a numeric argument, the argument is converted using the BEST12 
informat.
INPUT | OUTPUT | UPDATE
indicates the argument is either input to the routine, an output argument, or both. If 
you specify INPUT, the argument is converted and passed to the DLL routine. If you 
specify OUTPUT, the argument is not converted, but is updated with an outgoing 
value from the DLL routine. If you specify UPDATE, the argument is converted and 
passed to the DLL routine and updated with an outgoing value from the routine.
You can specify OUTPUT and UPDATE only with variable arguments (that is, no 
constants or expressions).
NOTREQD | REQUIRED
indicates whether the argument is required. If you specify NOTREQD, then 
MODULE can omit the argument. If other arguments follow the omitted argument, 
indicate the omitted argument by including an extra comma as a placeholder. For 
example, to omit the second argument to routine XYZ, you would specify: call 
module('XYZ',1,,3);
The SASCBTBL Attribute Table
295
VB.NET PDF Convert to Text SDK: Convert PDF to txt files in vb.net
VB.NET PDF - Convert PDF to Text Using VB. Integrate following RasterEdge text to PDF converter SDK dlls into your VB.NET project assemblies;
online pdf editor to delete text; how to edit and delete text in pdf file
C# PDF Text Search Library: search text inside PDF file in C#.net
Text: Search Text in PDF. C# Guide about How to Search Text in PDF Document and Obtain Text Content and Location Information with .NET PDF Control.
how to erase pdf text; how to delete text in pdf converter
CAUTION:
Be careful when using NOTREQD; the DLL routine must not attempt to 
access the argument if it is not supplied in the call to MODULE. If the 
routine does attempt to access it, your system is likely to crash.
The REQUIRED attribute indicates that the argument is required and cannot be 
omitted. REQUIRED is the default value.
BYADDR | BYVALUE
indicates the argument is passed by reference or by value.
BYADDR is the default value unless CALLSEQ=BYVALUE was specified in the 
ROUTINE statement, in that case BYVALUE is the default. Specify BYADDR when 
using a call-by-value routine that also has arguments to be passed by address.
FDSTART
indicates that the argument begins a block of values that is grouped into a structure 
whose pointer is passed as a single argument. Note that all subsequent arguments are 
treated as part of that structure until the MODULE function encounters another 
FDSTART argument.
FORMAT=format
names the format that presents the argument to the DLL routine. Any SAS Institute-
supplied formats, PROC FORMAT-style formats, or SAS/TOOLKIT formats are 
valid. Note that this format must have a corresponding valid informat if you 
specified the UPDATE or OUTPUT attribute for the argument.
The FORMAT= attribute is not required, but is recommended, since format 
specification is the primary purpose of the ARG statements in the attribute table.
CAUTION:
Using an incorrect format can produce invalid results or cause a system 
crash.
The Importance of the Attribute Table
MODULE routines rely heavily on the accuracy of the information in the attribute table. 
If this information is incorrect, unpredictable results can occur (including a system 
crash).
Consider an example routine xyz that expects two arguments: an integer and a pointer. 
The integer is a code indicating what action takes place. For example, action 1 means 
that a 20-byte character string is written into the area pointed to by the second argument, 
the pointer.
Now suppose you call xyz using the MODULE routine but indicating 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 given by the LENGTH statement for the second argument to 
MODULE, MODULE passes a pointer to a 10-byte area to the xyz routine. If xyz 
writes 20 bytes at that location, the 10 bytes of memory following the string provided by 
MODULE are overwritten, causing unpredictable results:
data _null_;
length x $20;
call module('xyz',1,x);
run;
296
Chapter 13 • Accessing External DLLs from SAS under Windows
The call might work fine, depending on which 10 bytes were overwritten. However, this 
action might also cause you to lose data or cause your system to crash.
Also, note that the PEEKLONG and PEEKCLONG functions rely on the validity of the 
pointers that you supply. If the pointers are invalid, it is possible that SAS could crash. 
For example, this code would cause a crash:
data _null_;
length c $10;
/* trying to copy from address 0!!!*/
c = peekclong(0,10); 
run;
Ensure that your pointers are valid when using PEEKLONG and PEEKCLONG.
Special Considerations When Using External 
DLLs
Using PEEKLONG Functions to Access Character String Arguments
Because the SAS language does not provide pointers as data types, you must use the 
PIB4. format and informat to represent pointers. You can then use the SAS PEEKLONG 
functions to access the data stored at these address values.
For example, suppose you have a routine named GetPath in a library named 
SERVICES.DLL. It has two arguments, an integer function code and a pointer to a 
pointer. The function code determines what action GetPath takes, and the second 
argument points to a pointer that is updated by GetPath to refer to a system character 
string. The calling code in C might be
GetPath(1,&stgptr);
printf("GetPath indicates string is
'%s'.\n",stgptr);
Using MODULE, the corresponding attribute table entry would be
ROUTINE GetPath MINARG=2 MAXARG=2
MODULE=SERVICES;
ARG 1 NUM INPUT BYVALUE FORMAT=PIB4.;
ARG 2 NUM OUTPUT BYADDR FORMAT=PIB4.;
and could be invoked as follows:
call module('GetPath',1,stgptr);
put stgptr= stgptr=hex8.;
If the pointer value in STGPTR is 0035F780, STGPTR would actually be set to the 
decimal value 3536768, which is the decimal equivalent of 0035F780. So the PUT 
statement above would produce:
STGPTR=3536768 STGPTR=0035F780
However, you want the data at address 0035F780, not the value of the pointer itself. To 
access that data, you need to use the PEEKCLONG function.
The PEEKCLONG function is given two arguments, a pointer via a numeric variable 
(such as STGPTR above) and a length in bytes (characters). PEEKCLONG returns a 
character string of the specified length containing the characters at the pointer location.
Special Considerations When Using External DLLs
297
In the example, suppose that GetPath sets the second argument's pointer value to the 
address of the null-terminated character string C:\XYZ. You can access the character 
data with:
call module('SERVICES,GetPath',1,stgptr);
length path $64;
path = peekclong(stgptr,64);
i = index(path,'00'x);
if i then substr(path,i)=' ';
/* path now contains the string */
The PEEKCLONG function copies 64 bytes starting at the location referred to by the 
pointer in STGPTR. Because you need only the data up to the null terminator (but not 
including it), you search for the null terminator with the INDEX function. Then you 
need to blank out all characters including and after that point.
You can also use the $CSTR format in this scenario to simplify your code slightly:
call module('SERVICES,GetPath',1,stgptr);
length path $64;
path = put(peekclong(stgptr,64),$cstr64.);
The $CSTR format accepts as input a character string of a specified width. It looks for a 
null terminator and pads the output string with blanks from that point.
For more information, see the “PEEKLONG Function” in SAS Functions and CALL 
Routines: Reference .
Accessing External DLLs Efficiently
The MODULE routine reads the attribute table referenced by the SASCBTBL fileref 
once per step (DATA step, PROC IML step, or SCL step). MODULE parses the table 
and stores the attribute information for future use during the step. When you use a 
MODULE function, SAS searches the stored attribute information for the matching 
routine and module names. The first time you access a DLL during a step, SAS loads the 
DLL, and determines the address of the requested routine. Each DLL that you invoke 
stays loaded for the duration of the step, and is not reloaded in subsequent calls. All 
modules and routines are unloaded at the end of the step. For example, suppose the 
attribute table had the basic form:
* routines XYZ and BBB in FIRST.DLL;
ROUTINE XYZ MINARG=1 MAXARG=1 MODULE=FIRST;
ARG 1 NUM INPUT;
ROUTINE BBB MINARG=1 MAXARG=1 MODULE=FIRST;
ARG 1 NUM INPUT;
* routines ABC and DDD in SECOND.DLL;
ROUTINE ABC MINARG=1 MAXARG=1 MODULE=SECOND;
ARG 1 NUM INPUT;
ROUTINE DDD MINARG=1 MAXARG=1 MODULE=SECOND;
ARG 1 NUM INPUT;
and the DATA step looked like:
filename sascbtbl 'myattr.tbl';
data _null_;
do i=1 to 50;
/* FIRST.DLL is loaded only once */
value = modulen('XYZ',i);
/* SECOND.DLL is loaded only once */
value2 = modulen('ABC',value);
298
Chapter 13 • Accessing External DLLs from SAS under Windows
put i= value= value2=;
end;
run;
In this example, MODULEN parses the attribute table during DATA step compilation. In 
the first loop iteration (i=1), FIRST.DLL is loaded and the XYZ routine is accessed 
when MODULEN calls for it. Next, SECOND.DLL is loaded and the ABC routine is 
accessed. For subsequent loop iterations (starting when i=2), FIRST.DLL and 
SECOND.DLL remain loaded, so the MODULEN function simply accesses the XYZ 
and ABC routines. SAS unloads both DLLs at the end of the DATA step.
Note that the attribute table can contain any number of descriptions for routines that are 
not accessed for a given step. This process does not cause any additional overhead (apart 
from a few bytes of internal memory to hold the attribute descriptions). In the above 
example, BBB and DDD are in the attribute table but are not accessed by the DATA step.
Grouping SAS Variables as Structure Arguments
A common need when calling external routines are to pass a pointer to a structure. Some 
parts of the structure might be used as input to the routine. Other parts might be replaced 
or filled in by the routine. Even though SAS does not have structures in its language, you 
can indicate to MODULE that you want a particular set of arguments grouped into a 
single structure. You indicate this structure by using the FDSTART option of the ARG 
statement to flag the argument that begins the structure in the attribute table. SAS 
gathers that argument and data (until encountering another FDSTART option) into a 
single contiguous block, and passes a pointer to the block as an argument to the DLL 
routine.
For example, consider the GetClientRect routine, which is part of the Win32 API in 
USER32.DLL. This routine retrieves the coordinates of a window's client area. This 
process also requires the use of another routine, GetForegroundWindow, to get the 
window handle for the window that you want the coordinates from.
The C prototypes for these routines are
HWND GetForegroundWindow(VOID);
BOOL GetClientRect(HWND hWnd, LPRECT lprc);
In C, the code to invoke them is:
typedef struct tagRECT {
int left;
int top;
int right;
int bottom;
} RECT;
/* RECT is a structure variable */
....                  /* other code */
/* Need the window handle first */
hWnd=GetForegroundWindow();
/* Function call, passing the address */
/* of RECT                            */
GetClientRect(hWnd, &RECT);
To call these routines using MODULE, you would use the following attribute table 
entries:
routine GetForegroundWindow
minarg=0
maxarg=0
Special Considerations When Using External DLLs
299
stackpop=called
module=USER32
returns=long;
routine GetClientRect
minarg=5
maxarg=5
stackpop=called
module=USER32;
arg 1 num input byvalue format=pib4.;
arg 2 num update fdstart format=ib4.;
arg 3 num update         format=ib4.;
arg 4 num update         format=ib4.;
arg 5 num update         format=ib4.;
with the following DATA step:
filename sascbtbl 'sascbtbl.dat';
data _null_;
hwnd=modulen('GetForegroundWindow');
call module('GetClientRect',hwnd,left,
top,right,bottom);
put left= top= right= bottom=;
run;
The use of the FDSTART option in the ARG statement for argument 2 indicates that 
argument 2 and all subsequent arguments are gathered into a single parameter block.
The output in the log from the PUT statement would look like:
LEFT=2 TOP=2 RIGHT=400 BOTTOM=587
Using Constants and Expressions as Arguments to MODULE
You can pass any type of expression as an argument to the MODULE functions. The 
attribute table indicates whether the argument is for input, output, or update.
You can specify input arguments as constants and arithmetic expressions. However, 
because output and update arguments must be able to be modified and returned, you can 
pass only a variable for these parameters. If you specify a constant or expression where a 
value that can be updated is expected, SAS issues a warning message pointing out the 
error. Processing continues, but the MODULE routine cannot update a constant or 
expression argument (meaning that the value of the argument that you wanted to update 
is lost).
Consider these examples. Here is the attribute table:
* attribute table entry for ABC;
routine abc minarg=2 maxarg=2;
arg 1 input format=ib4.;
arg 2 output format=ib4.;
Here is the DATA step with the MODULE calls:
data _null_;
x=5;
/* passing a variable as the    */
/*   second argument - OK       */
call module('abc',1,x);
/* passing a constant as the    */
/*   second argument - INVALID  */
300
Chapter 13 • Accessing External DLLs from SAS under Windows
Documents you may be interested
Documents you may be interested