• No results found

Declare (statement) 147 As an example of passing parameters by reference, consider the following C

In document Working Model 2D - User's Manual (Page 151-155)

Cross-Platform Scripting (topic)

Chapter 2 Declare (statement) 147 As an example of passing parameters by reference, consider the following C

routine which requires a pointer to an integer as the third parameter:

int SystemParametersInfo(int,int,int *,int);

This routine would be declared as follows (notice the ByRef keyword in the third parameter):

Declare Function SystemParametersInfo Lib "user" (ByVal action As Integer, _

ByVal uParam As Integer,ByRef pInfo As Integer, _ ByVal updateINI As Integer) As Integer

Strings can be passed by reference or by value. When they are passed by reference, a pointer to the internal handle to the WM Basic string is passed.

When they are passed by value, WM Basic passes a 32-bit pointer to a null-terminated string (i.e., a C string). If an external routine modifies a passed string variable, then there must be sufficient space within the string to hold the returned characters. This can be accomplished using the Space function, as shown in the following example:

Declare Sub GetWindowsDirectory Lib "kernel" (ByVal dirname$, ByVal length%)

:

Dim s As String s = Space(128)

GetWindowsDirectory s,128

Another alternative to ensure that a string has sufficient space is to declare the string with a fixed length:

Declare Sub GetWindowsDirectory Lib "kernel" (ByVal dirname$, ByVal length%)

:

Dim s As String * 128 'Declare a fixed-length string.

GetWindowsDirectory s,len(s) 'Pass it to an external subroutine.

Calling Conventions with External Routines

For external routines, the argument list must exactly match that of the

referenced routine. When calling an external subroutine or function, WM Basic needs to be told how that routine expects to receive its parameters and who is responsible for cleanup of the stack.

The following table describes which calling conventions are supported on which platform, and indicates what the default calling convention is when no explicit calling convention is specified in the Declare statement.

Supported Calling Default Calling Platform Conventions Convention Windows Pascal, CDecl Pascal

Macintosh Pascal, CDecl Pascal

Passing Null Pointers

To pass a null pointer to an external procedure, declare the parameter that is to receive the null pointer as type Any, then pass a long value 0 by value:

Declare Sub Foo Lib "sample" (ByVal lpName As Any) Sub Main()

Sub Foo "Hello" 'Pass a 32-bit pointer to a null-terminated string

Sub Foo ByVal 0& 'Pass a null pointer End Sub

Passing Data to External Routines

The following table shows how the different data types are passed to external routines:

Data Type Is Passed As

ByRef Boolean A 32-bit pointer to a 2-byte value containing –1 or 0.

ByVal Boolean A 2-byte value containing –1 or 0.

ByVal Integer A 32-bit pointer to a 2-byte short integer.

ByRef Integer A 2-byte short integer.

ByVal Long A 32-bit pointer to a 4-byte long integer.

ByRef Long A 4-byte long integer.

ByRef Single A 32-bit pointer to a 4-byte IEEE floating-point value (a float).

ByVal Single A 4-byte IEEE floating-point value (a float).

ByRef Double A 32-bit pointer to an 8-byte IEEE floating-point value (a double).

ByVal Double An 8-byte IEEE floating-point value (a double).

ByVal String A 32-bit pointer to a null-terminated string. With strings containing embedded nulls (Chr$(0)), it is not possible to determine which null represents the end of the string. Therefore, the first null is considered the string terminator.

An external routine can freely change the content of a string. It cannot, however, write beyond the end of the null terminator.

ByRef String A 32-bit pointer to a 2-byte internal value representing the string. This value can only be used by external routines written specifically for WM Basic.

ByRef Date A 32-bit pointer to an 8-byte IEEE floating-point value (a double).

ByVal Date An 8-byte IEEE floating-point value (a double).

ByRef Currency A 32-bit pointer to an 8-byte integer scaled by 10000.

ByVal Currency An 8-byte integer scaled by 10000.

Chapter 2 Declare (statement) 149

ByRef Variant A 32-bit pointer to a 16-byte internal variant structure. This structure contains a 2-byte type (the same as that returned by the VarType function), followed by 6 bytes of slop (for alignment), followed by 8 bytes containing the value.

ByVal Variant A 16-byte variant structure. This structure contains a 2-byte type (the same as that returned by the VarType function), followed by 6 bytes of slop (for alignment), followed by 8 bytes containing the value.

ByVal Object For data objects, a 32-bit pointer to a 4-byte unsigned long integer. This value can only be used by external routines written specifically for WM Basic.

For OLE automation objects, a 32-bit pointer to an LPDISPATCH handle is passed.

ByRef Object For data objects, a 32-bit pointer to a 4-byte unsigned long integer that

references the object. This value can only be used by external routines written specifically for BasicScript.

For OLE automation objects, a 32-bit pointer to a 4-byte internal ID is passed.

This value can only be used by external routines written specifically for WM Basic.

User-defined type A 32-bit pointer to the structure. User-defined types can only be passed by reference.

It is important to remember that structures in WM Basic are packed on 2-byte boundaries, meaning that the individual structure members may not be aligned consistently with similar structures declared in C.

Arrays A 32-bit pointer to a packed array of elements of the given type. Arrays can only be passed by reference.

Dialogs Dialogs cannot be passed to external routines.

Only variable-length strings can be passed to external routines; fixed-length strings are automatically converted to variable-length strings.

WM Basic passes data to external functions consistent with that routine's prototype as defined by the Declare statement. There is one exception to this rule: you can override ByRef parameters using the ByVal keyword when passing individual parameters. The following example shows a number of different ways to pass an Integer to an external routine called Foo:

Declare Sub Foo Lib "MyLib" (ByRef i As Integer) Sub Main

Dim i As Integer i = 6

Foo 6 'Passes a temporary integer (value 6) by reference Foo i 'Passes variable "i" by reference

Foo (i) 'Passes a temporary integer (value 6) by reference Foo i + 1 'Passes temporary integer (value 7) by reference Foo ByVal i 'Passes i by value

End Sub

The above example shows that the only way to override passing a value by reference is to use the ByVal keyword.

Note: Use caution when using the ByVal keyword in this way. The external routine Foo expects to receive a pointer to an Integer—a 32-bit value; using

ByVal causes WM Basic to pass the Integer by value—a 16-bit value. Passing data of the wrong size to any external routine will have unpredictable results.

Example Declare Function IsLoaded% Lib "Kernel" Alias "GetModuleHandle" (ByVal name$)

Declare Function GetProfileString Lib "Kernel" (ByVal SName$,ByVal KName$,_

ByVal Def$,ByVal Ret$,ByVal Size%) As Integer Sub Main()

SName$ = "Intl" 'Win.ini section name.

KName$ = "sCountry" 'Win.ini country setting.

ret$ = String$(255, 0) 'Initialize return string.

If GetProfileString(SName$,KName$,"",ret$,Len(ret$)) Then MsgBox "Your country setting is: " & ret$

Else

MsgBox "There is no country setting in your win.ini file."

End If

If IsLoaded("Progman") Then MsgBox "Progman is loaded."

Else

MsgBox "Progman is not loaded."

End If End Sub

See Also Call (statement), Sub...End Sub (statement), Function...End Function

(statement).

Chapter 2 Declare (statement) 151

In document Working Model 2D - User's Manual (Page 151-155)