DLL Declaration

Action

Declares functions in a DLL so that they can be called from a 4Test script.

Syntax

dll dllname.dll
prototype
[prototype]...
Variable Description
dllname The name of the DLL file that contains the functions you want to call.
prototype The function prototype of a DLL function you want to call. Each prototype has the syntax shown below.

Prototype Syntax

[return-type] func-name ( [arg-list]) [alias dll-fname]
Variable Description
return-type Optional: The data type of the return value, if there is one.
func-name An identifier that specifies the name of the function.
dll-fname Optional: A string that specifies the name of the function within the DLL. If specified, func-name is the alias name to be used in 4Test. See the example below.
arg-list Optional: A comma-delimited list of arguments. Each argument in arg-list has the syntax shown below.

Argument Syntax

[pass-mode] data-type arg-name
Variable Description
pass-mode Optional: Whether the argument is passed into the function, passed out of the function, or both. pass-mode can be in, out, or inout. The default is in. See Function Declaration for a description of pass modes.
data-type The C data type of the argument. See the information on C data types below.
arg-name An identifier specifying the name of the argument.

Notes

Alias Names

If a DLL function has the same name as a 4Test reserved word, or the function does not have a name but an ordinal number, rename the function within your 4Test declaration and use the alias keyword to map the declared name to the actual name. The second example below defines an alias name for the DLL function exit.

C Data Types

Since DLL functions are written in C, the arguments you pass to these functions must have C data types or be records containing fields of these types. For a list of these data types, see C data types for DLL functions.

Copying and Freeing DLL Memory

When a DLL function uses a string as the return type, Silk Test Classic does not assume ownership of that string. The reason for this is that buffers must be de-allocated in the same C-Runtime as they were allocated. Otherwise, the application might crash. Therefore, Silk Test Classic looks for a function called FreeDllMemory which accepts a pointer in the DLL's interface. If available, Silk Test Classic calls that function with the buffer as argument, and gives the DLL a chance to clean up its memory. Otherwise, Silk Test Classic leaves the buffer as it is (leaking memory) because it has no way of freeing the memory without risking a crash.

Output String Buffer

If the user calls a DLL function with an output string buffer that is less then the minimum size of 256 characters, the original string buffer is resized to 256 characters and a warning is printed. This warning, "String buffer size was increased from x to 256 characters" (where x is the length of the given string plus one) alerts the user to a potential problem where the buffer used might be shorter than necessary.

Passing Arguments

The table below provides additional information about passing certain types of arguments to DLL functions:

Variable Type How to Pass
Pointer to a character Pass a 4Test string variable to a DLL which requires a pointer to a character (null terminated).
Pointer to a numerical array Pass a 4Test array or list of the appropriate type to a DLL which requires a pointer to a numerical array.
Pointer to a record Pass a 4Test record to a DLL which requires a pointer to a record. If the record has a dwSize field, then you must set it to the size of the record. 4Test records are always passed by reference to a DLL.
Pointer to a function You cannot pass a pointer to a function to a DLL function.
Null string pointer To pass a null pointer to a string, use the null keyword in 4Test.
Window handle Use the hWnd property or the GetHandle method of the AnyWin class to get the window handle you need.

Arguments Passed by Reference by the DLL Function

A few special rules apply for declaring arguments that can be passed by reference by the DLL function:

  • Declare an argument whose value will be passed by reference by a DLL function using the out keyword.

  • Declare an argument that is sometimes passed by reference and sometimes not using the in keyword. In the call to the DLL function, preface the argument with the out keyword, enclosed in brackets.

inprocess Keyword

Typically, when you make a DLL function call, the DLL gets loaded into the Agent and called from there. However, if you specify that a function is "inprocess", it uses the first argument (which has to be a window handle - not the window id) and loads the DLL into that application's process. If the DLL's function's first argument is not a window handle, you must write a wrapper so that it is. For example, your DLL declaration might say: inprocess SendMessage(HWND ......

and then when you call SendMessage, it is loaded into the application that contains the window handle you provided.

If there is a return type, the return type comes after the inprocess keyword.

You can have DLL functions that are both inprocess and not inprocess by using aliases.

ansicall Keyword

The ansicall keyword converts all string parameters (return type, string arguments, strings in record structures that are used as arguments) from W (wide-character, Unicode) to A (ANSI) character format before calling the DLL function internally. Return values and pass-mode variables set to inout that are strings or contain strings within record structures get converted back from A (ANSI) format to W (wide-character) format after calling the DLL. Using the ansicall keyword makes an ANSI call transparent, as the conversion is done internally.

Note: The DLL calling stack does not support return values that are pointers to a record structure. To determine if the function succeeded, use the inout or out pass-mode variable and use the return-type variable as a flag.
Important: If you use DLL functions where you specify string sizes in bytes, remember that W (wide-character) strings are assigned 2 bytes per character, and A (ANSI) strings are assigned 1 byte per character. If you pass a buffer of 1000 characters via an ANSI call, you use 1000 bytes of space, not 2000 bytes. But if you return a string of 1000 characters from a DLL, the W (wide-character) buffer will have 2000 bytes.

Example

You can use the inprocess and ansicall keywords together in the same DLL call:

inprocess ansicall INT MessageBoxIPA (HWND hWndParent, LPCSTR sText, LPCSTR sTitle, UINT fuFlags) alias "MessageBoxA"