TECHNICAL BULLETIN #117 - Rev 1.00 (7/30/96) ============================================================================== TITLE : DLLs and Windows ASPECT: PASCAL Language Specifications PRODUCT : Procomm Plus 4.x, 3.x ============================================================================== Procomm Plus implements a powerful scripting language called the Windows ASPECT Script Language (ASPECT). One of ASPECT's strengths is the ability to call functions embedded in Dynamic Link Libraries (DLLs) written and compiled outside of ASPECT. This paper focuses on writing DLLs for ASPECT using Turbo Pascal for Windows (TPW) from Borland International, Inc. ASPECT TO DLL PARAMETER SEQUENCE ASPECT generates a standard parameter block for every DLL call that it makes. This standard parameter block has five parameters, listed in order below. When writing a DLL to be called from ASPECT, every exported function that is to be accessible from within ASPECT should declare these parameters: 1. [HWnd] - a handle to the Procomm Plus main window. 2. [THandle] - a handle to the instance of Procomm Plus that made the DLL call. 3. [pointer to array[0..9] of pointer] - a pointer to an array of pointers to the data elements listed as parameters on the ASPECT script line that called the DLL function. 4. [pointer to array[0..9] of byte] - a pointer to an array of bytes. Byte N of this array describes the type of element N stored in the array of data elements (i.e. parameter 3). The range of values in this array follows this scheme: Byte Value Meaning --------------------------------------------- 0 nth element is an ASPECT string 1 nth element is an ASPECT integer 2 nth element is an ASPECT long 3 nth element is an ASPECT float 5. [int] - an integer containing the count of parameters provided on the ASPECT script line calling the DLL function AN EXAMPLE DLL Here is the code for a DLL with a function that generates a random number. Under a PASCAL style, stack-based parameter passing scheme, a variable number of parameters is not normally possible; however, ASPECT provides an array-based parameter passing scheme as described by the parameter block above. To demonstrate the ability to pass a variable number of parameters, the DLL function listed below makes certain assumptions about the provided parameters based on the number of parameters that are available: 1. If two parameters are passed to the DLL function, the first parameter holds a number for seeding the random-number generator and the second parameter will hold the return value (i.e. the random number). 2. If one parameter is passed to the DLL function, the DLL function should seed the random number generator using the Randomize function from the TPW System Unit and the parameter will hold the return value (i.e. the random number). Sample DLL: RANDINT.PAS library RandInt; uses WinTypes; const IntegerType = 1; LongType = 2; MaxWord: Word = 65535; type pdatptrary = ^tdatptrary; tdatptrary = array[0..9] of pointer; ptypptrary = ^ttypptrary; ttypptrary = array[0..9] of byte; function RandomInt(PWWnd: HWnd; PWInst: THandle; PData: pdatptrary; PType: ptypptrary; argcnt: integer): BOOL; export; begin if (argcnt < 1) then begin {at least one arg?} RandomInt := FALSE; {if not, return failure to Aspect} exit; end; if (argcnt > 1) then begin if ((PType^[0] <> LongType) or (PType^[1] <> IntegerType)) then begin RandomInt := FALSE; {for two args, 1=long, 2=int} exit; {if not, return failure to Aspect} end; RandSeed := PLongint(PData^[0])^; {seed generator} PWord(PData^[1])^ := Random(MaxWord); {get the random number} end else begin if (PType^[0] <> IntegerType) then begin RandomInt := False; {for one arg, 1=int} exit; {if not, return failure to Aspect} end; Randomize; {seed generator with time} PWord(PData^[0])^ := Random(MaxWord); {get the random number} end; RandomInt := True; {return success to aspect} end; exports RandomInt index 1; begin end. Sample ASPECT script: RANDINT.WAS: ;ASPECT script demonstrating RANDINT.DLL integer hdll, rnum long seed = 1060665 proc cleanup dllfree hdll exit endproc proc main string DLLPATH = "C:\PROWIN\ASPECT\RANDINT.DLL" ;path to the DLL when userexit call cleanup ;point to cleanup routine dllload DLLPATH hdll ;load the DLL if (failure) usermsg "dllload failed" exit endif ;generate a random number letting the DLL use system time as seed dllcall hdll "RandomInt" rNum if (failure) usermsg "RandomInt call with system time seed failed" cleanup() else usermsg "RandomInt with system time seed returned %u" rNum endif ;generate a random number with the our seed dllcall hdll "RandomInt" seed rNum if (failure) usermsg "RandomInt call with our seed failed" cleanup() else usermsg "RandomInt with our seed returned %u" rNum endif cleanup() endproc ============================================================================== To ensure that you have the latest version of this document, compare its revision number to that of the same document on any of our support sites. This technical bulletin may be copied and distributed freely as long as it is distributed in its entirety and it is not distributed for profit. Copyright (c) 1996 Quarterdeck All rights reserved. ==============================================================================