変数の保持容量を拡大したり、メモリを解放したりします。通常は必要ありませんが、DllCallや SendMessageと併用したり、繰り返しの連結を最適化するために使用されることがあります。
GrantedCapacity := VarSetStrCapacity(&TargetVar , RequestedCapacity)
型:VarRef
変数への参照。事例:VarSetStrCapacity(&MyVar, 1000)。This can also be a dynamic variable such as MyArray%i% or a function's ByRef parameter.
Type: Integer
省略されたときは、変数の現在の容量が返され、その内容は変更されません。そうでなければ、現在変数に入っているものはすべて失われます(変数は空白になります)。
RequestedCapacityには、調整後に変数が保持できる文字数を指定する。RequestedCapacityには内部ゼロターミネータは含まれない。例えば、1を指定すると、内部ターミネーターに加えて1文字まで保持することができる。注:この変数は、スクリプトが後で大きな値を代入した場合に自動的に拡張されます。
この関数は、単に変数の最小容量を確保するために呼ばれることが多いので、パフォーマンス上の理由から、RequestedCapacityが0のときだけ変数を縮小する。言い換えれば、変数の容量がすでにRequestedCapacityより大きい場合、それは減少しない(しかし、一貫性のために変数はまだ空白にされる)。
したがって、変数を明示的に縮小するには、まずVarSetStrCapacity(&Var, 0)でメモリを解放し、次にVarSetStrCapacity(&Var, NewCapacity)を使う。
性能上の理由から、以前の容量が64文字未満の変数を解放しても、そのメモリは永久型であるため、何の効果もないかもしれない。この場合、0ではなく現在の容量が返される。
パフォーマンス上の理由から、容量が4096バイト未満の変数に空文字列を格納してもメモリは解放されない(例:Var := "")。しかし、VarSetStrCapacity(&Var, 0)はそれを解放する。
RequestedCapacityに-1を指定すると、変数の内部に格納されている文字列の長さが、現在の内容の長さに更新される。これは、DllCallや SendMessageでアドレスを渡すなど、文字列が間接的に変更された場合に便利である。このモードでは、VarSetStrCapacityは容量ではなく長さを返す。
Type: Integer
この関数は、TargetVarが現在保持できる文字数を返し、これはRequestedCapacity以上となる。
例外は、以下のいずれかの条件でスローされる:
Bufferオブジェクトは、バイナリ・データ、構造体、DllCallなどを扱う際に、優れた明快さと柔軟性を提供する。例えば、Bufferオブジェクトはその内容をコピーすることなく、プロパティや配列要素に代入したり、関数に渡したり関数から返したりすることができる。
この関数は、漸進的な連結によって文字列を構築する際のパフォーマンスを向上させるために使用できる。これは、文字列の最終的な長さがある程度わかっていれば、何度も自動的にリサイズすることを避けられるからである。その場合、RequestedCapacityは正確である必要はない:容量が小さすぎる場合でも、パフォーマンスは改善され、容量がなくなると変数は自動拡張を開始する。容量が大きすぎる場合、メモリの一部が無駄になるが、VarSetStrCapacity(&Var, 0)またはVar := ""によって操作後にすべてのメモリを解放できるため、一時的なものに過ぎない。
Bufferオブジェクト、DllCall、NumPut、NumGet
VarSetStrCapacity(&MyVar, 5120000) ; ~10 MB
Loop
{
; ...
MyVar .= StringToConcatenate
; ...
}
変数を使用して、DllCallを介して外部関数から文字列を受け取る。(特にUnicode以外の文字列を扱う場合は、Bufferオブジェクトを使用する方が好ましいかもしれないことに注意してください。)
max_chars := 10
Loop 2
{
; Allocate space for use with DllCall.
VarSetStrCapacity(&buf, max_chars)
if (A_Index = 1)
; Alter the variable indirectly via DllCall.
DllCall("wsprintf", "Ptr", StrPtr(buf), "Str", "0x%08x", "UInt", 4919, "CDecl")
else
; Use "str" to update the length automatically:
DllCall("wsprintf", "Str", buf, "Str", "0x%08x", "UInt", 4919, "CDecl")
; Concatenate a string to demonstrate why the length needs to be updated:
wrong_str := buf . "<end>"
wrong_len := StrLen(buf)
; Update the variable's length.
VarSetStrCapacity(&buf, -1)
right_str := buf . "<end>"
right_len := StrLen(buf)
MsgBox
(
"Before updating
String: " wrong_str "
Length: " wrong_len "
After updating
String: " right_str "
Length: " right_len
)
}