Passing arrays, types, and objects

Passing arrays as arguments

Because LotusScript® stores an array in a private format, you can pass an array by reference to a C function only if the function is specifically written for LotusScript®. The following example shows how to declare and implement a C function that takes a LotusScript® array of long values.

In LotusScript®:

Declare Function LSArrayArg Lib "MYDLL" (ArrLng () As Long)_
 As Long
Dim MyArr(0 to 5) As Long
Print LSArrayArg(MyArr)

In C:

long C_CALL_TYPE LSArrayArg(LSsValueArray *pLSArr)
{
     long *pData=pLSArr->Data; 
      //pData points to first array element
     return pData[0]+pData[1]; //Sum first 2 array elements
}

Or:

long C_CALL_TYPE LSArrayArg(long **pLSArr)
{
     long *pData=*pLSArr; 
     //pData points to first array element
     return pData[0]+pData[1]; //Sum first 2 array elements

C_CALL_TYPE is the calling convention: Pascal, STDCALL, _System, or CDECL.

Other C functions may require an array, such as the Windows function SetBitmapBits. You can still pass the array by passing the first array element by reference with the Any keyword, as shown in the following example.

In LotusScript®:

Declare Function FncArrayArg(A As Any) As Long
Dim MyArr(0 to 5) As Long
Print FncArrayArg(MyArr(0))

In C:

long C_CALL_TYPE FncArrayArg(long *pArr)
{
     return pArr[0]+pArr[1]; //Sum first 2 array elements
}

Passing types as arguments

Some C functions can require a data structure as a parameter. An example is the Windows API function GetBrushOrgEx, which requires a pointer to a point structure. You can define a suitable data type, such as Point, and use that type definition to declare the C function. Since type variables are passed by reference, the C function receives a 4-byte pointer to the storage for the type variable.

LotusScript® allows you to specify an optional string type, Unicode or LMBCS, on a type parameter in the Declare statement for a C function. The declarations have this form, for a function UniTest with one type argument and a function LMBCSTest with one type argument, where t1 is a user-defined data type:

Declare Function UniTest Lib "Unilib" (typArg As Unicode t1)_
 As Long
Declare Function LMBCSTest Lib "lmbcslib" _
 (typArg As LMBCS t1) As Long

In the first example, all strings (fixed-length and variable-length) in type t1 and any of its nested types will be passed as Unicode strings. In the second example, all strings in type t1 (fixed- and variable-length) and any of its nested types will be passed as LMBCS strings.

If Unicode or LMBCS is not specified in this way, the default is to pass all strings in a type argument in the platform-native character set. This is compatible with LotusScript® Release 2.

Strings contained in Variants in the type will not be affected. This change is incompatible with LotusScript® Release 2, because translation to platform will be invoked by default on types containing strings (previously, these strings would have been passed as platform-native character set strings).

If the type contains a fixed-length non-Unicode string, the entire structure must be copied and its size adjusted. The size of the structure will be smaller (each fixed-length string will contain half as many bytes when translated to platform or LMBCS, since the length of the string is fixed and must be preserved). This implies that the string may be truncated (lose information) because a Unicode string of length 20 may require more than 20 bytes to represent in platform (DBCS). The loss cannot occur with variable-length strings, since they are represented as pointers.

LotusScript® aligns type members to their natural boundaries for cross-platform transportability:

Data type

Alignment

Boolean

2 bytes

Byte

1 byte

Integer

2 bytes

Long

4 bytes

Single

4 bytes

Double

8 bytes

Currency

4 bytes

String (LMBCS)

2 bytes

String (Unicode)

2 bytes

String (Platform)

1 byte

Variant

8 bytes

The resulting alignment will not match the platform-specific alignment on Windows 3.1 and Windows 95. For example, LotusScript® aligns the type member B on a 4-byte boundary, while the default alignment in Windows 3.1 will be on a 2-byte boundary.

Type telMet
   A As Integer
   B As Long
End Type

Passing objects as arguments

When an object is passed to a C function, the function receives a 4-byte pointer to the unpacked data in the object. Because the data may include pointers to strings, arrays, lists, and product objects, it is unlikely that the C function has full knowledge of the internal structure of the object. You should use a C function to manipulate only the simplest objects.

Example 1

' The following statements declare the C function
' SetBitmapBits.Its 3rd argument is an array argument. This is 
' declared as type Any. In the function call, passing
' bitArray(0) passes the array by reference. 
Declare Sub SetBitmapBits Lib "_privDispSys" _ 
   (ByVal hBM As Integer, ByVal cBytes As Long, pBits As Any)
' ...
SetBitmapBits(hBitmap, cBytesInArray, bitArray(0))

Example 2

type mytype
	mName as string
end type

class myclass
	mName as string
end class

function VariantParam( v as Variant) as string
	dim tempstr as string
	tempstr = TypeName(v)
	VariantParam = tempstr
end function

sub initialize
	dim myinteger as integer
	dim mylong as long
	dim mystring as string
	dim myintlist list as integer
	dim myintarray() as integer
	dim mymytype as mytype
	dim mymyclass as myclass

	messagebox variantparam(myintlist)

	messagebox variantparam(myintarray)

'	Error: Type mismatch on: MYMYTYPE
'	messagebox variantparam(mymytype)

	messagebox variantparam(mymyclass)

end sub