配列、型、オブジェクトを引き渡す

OS/2 では、C 関数への配列、型、オブジェクトの引数の引き渡しはサポートされていません。

配列を引数として引き渡す

LotusScript® では、配列はプライベートな形式で格納されるので、C 関数が LotusScript 用に特別に作成されていなければ、C 関数に配列を参照渡しできません。以下の例では LotusScript から long 型の配列を参照する C 関数の宣言と実行の方法を示しています。

LotusScript:

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

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
}

または、

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 は、呼び出し規則 (Pascal、STDCALL、_System、CDECL です。

他の C 関数では Windows 関数 SetBitmapBits のような配列が必要な場合もあります。次の例のようにキーワード Any の参照を使用して、配列の先頭の値を引き渡すこともできます。

LotusScript:

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

C 関数:

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

型を引数として引き渡す

C 関数の中には、パラメータとしてのデータ構造体を必要とするものがあります。例えば、Windows API 関数の GetBrushOrgEx は、構造体を示すポインタを必要とします。Point など、適切なデータ型を定義し、その型定義を使用して C 関数を宣言できます。型変数は参照渡しされるので、C 関数はその型の変数を記憶している領域への 4 バイトのポインタを受け取ります。

LotusScript では、C 関数の Declare ステートメントの型パラメータで、省略可能な string 型、Unicode または LMBCS を指定できます。型の引数を 1 つとる関数 UniTest、および型の引数を 1 つとる関数 LMBCSTest の場合、宣言は次の形式になります。この場合、t1 はユーザー定義のデータ型です。

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

最初の例で、t1 型とそこにネストされた型のすべての文字列 (固定長と可変長) は、Unicode 文字列として渡されます。第 2 の例で、t1 型とそこにネストされた型のすべての文字列 (固定長と可変長) は、LMBCS 文字列として渡されます。

この方法で Unicode または LMBCS を指定しなければ、デフォルトでは、型の引数内のすべての文字列がプラットフォーム固有の文字セットで渡されます。これは LotusScript リリース 2 との互換性があります。

Variant 型の変数に含まれる文字列には、影響はありません。この変更には LotusScript リリース 2 との互換性がないので注意してください。これは、プラットフォームに対する変換が、既定で文字列を含む型に呼び出されるからです (以前は、これらの文字列はプラットフォーム固有の文字セット文字列として渡されていました)。

型に固定長の Unicode でない文字列が入っている場合は、構造体全体をコピーして、そのサイズを調整しなければなりません。構造体のサイズは小さくなります (文字列の長さは固定で、保持しなければならないため、各固定長文字列のバイト数はプラットフォームまたは LMBCS に変換すると半分になります)。これは、長さが 20 の Unicode 文字列をプラットフォーム (DBCS) 内で表すには 20 バイト超が必要なので、文字列が切り捨てられる (情報が失われる) 可能性があることを暗示しています。可変長文字列はポインタとして表されるので、情報は失われません。

LotusScript は、型のメンバをその本来の境界に合わせて、プラットフォーム間で変換できるようにします。

データ型

境界合わせ

Boolean 型

2 バイト

Byte

1 バイト

Integer

2 バイト

Long 型

4 バイト

Single

4 バイト

Double 型

8 バイト

Currency 型

4 バイト

String 型 (LMBCS)

2 バイト

String 型 (Unicode)

2 バイト

String 型 (プラットフォーム)

1 バイト

Variant 型

8 バイト

境界合わせの結果は、Windows 3.1 や Windows 95 のプラットフォーム固有の境界とは一致しなくなります。例えば、LotusScript では型のメンバ B が 4 バイト境界上に合わせられますが、Windows 3.1 では 2 バイトの境界上になります。

Type telMet
   A As Integer
   B As Long
End Type

オブジェクトを引数として引き渡す

オブジェクトを C 関数に渡すと、C 関数はオブジェクト内で取り出されたデータへの 4 バイトのポインタを受け取ります。データには文字列、配列、リスト、製品固有のオブジェクトへのポインタが含まれることがあるので、C 関数がオブジェクトの内部構造体を完全に認識しないことがあります。C 関数は、最も単純なオブジェクトを操作するときにだけ使用するようにしてください。

例 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))

例 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