LotusScript では、コールアウトを使用してネイティブ C APIと連携し、メモリポインタを取得・操作できます。
例えば、以下のコードは、メモリハンドルをロックし、ポインタを取得し、メモリブロックを手動で走査する方法を示しています。
Dim ptr As Long
ptr = OSLockObject(handle_to_buffer)
Print ptr
ptr = ptr + 1 ' Move pointer forward (byte-wise traversal)
...
...
OSUnlockObject(handle_to_buffer)
この手法は 32 ビット版の HCL Notes では機能しますが、基本的なアーキテクチャの違いにより 64 ビット HCL Notes では機能しません。
- 32 ビット システムでは、Long データ型とメモリポインターはどちらも 4 バイトのサイズです。
- 64 ビット システムでは、メモリ ポインタは 8 バイトに拡張されますが、LotusScript の Long 型は 4 バイトのままです。
- LotusScript は元々 8 バイトのポインターに対応するように設計されていなかったため、不正な動作やクラッシュが発生しました。
回避策: Double をポインタとして使用する
この制限に対処するための実用的な回避策として、LotusScript でネイティブに使用できる 8 バイトサイズの Double データ型を利用する方法があります。Double は通常、浮動小数点演算に使用されますが、64 ビットのポインタ値を保持するために再利用することもできます。
この機能を有効にするために、NotesSessionクラスにUseDoubleAsPointerプロパティが用意されました。このプロパティをTrueに設定すると、LotusScript エンジンは Double 変数を生のポインタとして扱うようになります。
Dim d As Double
session.UseDoubleAsPointer = True
' Use 'd' as a pointer
session.UseDoubleAsPointer = False
' Reverts 'd' to standard floating-point behavior
64 ビットシステムにおけるポインタ演算
Double 型を用いてポインタ演算を実行しようとすると、微妙ながらも重大な問題が発生します。値はポインタとして格納されているにもかかわらず、内部的には浮動小数点数として表現されます。
その結果、次のような ptr = ptr + 1 の演算は 期待通りに動作しません。浮動小数点数に 1 を加算しても、メモリ内の次のバイトに進むとは限りません。
session.UseDoubleAsPointer = True
Dim ptr As Double
ptr = OSLockObject(handle_to_buffer) ' Value may appear like 2.751542356E+18
ptr = ptr + 1 ' INCORRECT: Not valid pointer arithmetic
session.UseDoubleAsPointer = False