DLL.DefineType Method

Applies to TestComplete 15.47, last modified on January 20, 2023

Description

When calling routines from a dynamic link library, you may need to use data types incompatible with OLE. For instance, you may need to call a function that takes a pointer to a structure as a parameter. The DLL.DefineType method "registers" a new data type (normally, a structure) in TestComplete and returns the ID of the new data type. Later, you can use this ID to specify the type of function parameters or structure members.

Declaration

DLL.DefineType(TypeName, MemberType1, MemberName1, MemberType2, MemberName2, ..., MemberTypeN, MemberNameN)

TypeName [in]    Required    String    
MemberType1 [in]    Required    Integer    
MemberName1 [in]    Required    String    
MemberType2 [in]    Optional    Integer    
MemberName2 [in]    Optional    String    
...
MemberTypeN [in]    Optional    Integer    
MemberNameN [in]    Optional    String    
Result Integer

Applies To

The method is applied to the following object:

Parameters

The method uses a variable number of parameters.

All parameters of the DefineType method, except for the TypeName parameter, specify the types and names of structure members. These parameters can be divided into pairs: MemberType-MemberName. Only the first pair is required, other pairs are optional.

TypeName

A required parameter that designates the name of the data type to be defined. TypeName can include any characters. For instance, if you define a structure, this parameter holds the structure name. Later, this name is used to create the structure and fill it with data.

MemberType

An integer that specifies the member’s data type. It can be one of predefined constants or an ID created by the previous call to DefineType.

If a member is passed by a reference, you must use the vt_byref constant when you declare its type (see the example below).

Note that currently it is impossible to call DLL routines that use structures containing array-type members (for instance, string or array fields):

Delphi

// A definition of structure in the DLL source
type
  TMyStruct1 = record
    FInteger:Integer;
    CharArray: array[0..9] of Char; // The array is used
  end;
...
// This routine will not operate properly when it is called from TestComplete
procedure AcceptStructure(const AValue: TMyStruct1); stdcall;

When you try to do this, you will not get an error, but the array-type field will be undefined even if you assign a value to it.

You can workaround this limitation by using pointer-type members:

Delphi

// A definition of structure in the DLL source
type
  TMyStruct2 = record
    FInteger:Integer;
    CharArrPtr: PChar; // The pointer is used
  end;
...
// This routine will function correctly in TestComplete
procedure AcceptStructure(const AValue: TMyStruct2); stdcall;

Make sure that you specified the member types correctly. Incorrect definition of data types may cause TestComplete to shut down when passing such structures to DLL functions from tests (this happens because erroneous definitions may cause incorrect stack processing).
MemberName

The name of the structure member. This name is used to access the structure member from scripts. That is why it must comply with the naming rules of the used scripting language. Besides that, members must have unique names in the structure.

Result Value

The integer value that denotes the identifier of the created data type.

Remarks

DefineType registers a new data type, but it does not create variables of this type. To create variables, call DLL.New.

If the method registers the data type that was registered earlier in the current test or in a previous test (if the ClearSettingsBeforeEach run option is enabled), it posts a warning message to the test log.

Compilers can align structure members at certain addresses multiplied by 1, 2, 4 or more bytes. For instance, often an application uses the double word alignment (4 byte). The alignment may enlarge the actual size of structure members that take less memory than the alignment value. You should keep that in mind when using this method, as TestComplete does not align structure members.

By default, the compilers use alignment for structures that are defined by default, that is, without the use of the #pragma pack(...) statement in C++ code or packed record in Delphi. When creating a data type for these structures in scripts, pay attention to the size of structure members.

To control alignment, use the DefineTypeWithAlignment method.

Example

The following example illustrates defining structures in TestComplete:

JavaScript, JScript

DefType = DLL.DefineType("MyStruct", // name of the new structure
vt_i4, "Value", // integer
vt_byref | vt_i4, "ValueByRef", // pointer to integer
vt_byref | myID, "MyStruct2"); // pointer to structure MyStruct2

Python

DefType = DLL.DefineType("MyStruct",  # name of the new structure
vt_i4, "Value", # integer
vt_byref | vt_i4, "ValueByRef", # pointer to integer
vt_byref | myID, "MyStruct2") # pointer to structure MyStruct2

VBScript

' The 1st parameter is the structure name
' The 2nd parameter is an integer value
' The 3rd parameter is a pointer to an integer value
' The 4th parameter is a pointer to structure
DefType = DLL.DefineType("MyStruct", _
vt_i4, "Value", _
vt_byref or vt_i4, "ValueByRef", _
vt_byref or myID, "MyStruct2")

DelphiScript

DefType := DLL.DefineType('MyStruct', // name of the new structure
vt_i4, 'Value', // integer
vt_byref or vt_i4, 'ValueByRef', // pointer to integer
vt_byref or myID, 'MyStruct2'); // pointer to structure MyStruct2

C++Script, C#Script

DefType = DLL["DefineType"]("MyStruct", // name of the new structure
vt_i4, "Value", // integer
vt_byref | vt_i4, "ValueByRef", // pointer to integer
vt_byref | myID, "MyStruct2"); // pointer to structure MyStruct2

See Also

Calling DLL Functions From Tests - Tutorial
IDefineDLL Object
DefineTypeWithAlignment Method

Highlight search results