因为 Inno Setup 没有提供 PWideChar 类型(Dephi 中有?),而只提供了 PAnsiChar,如果需要接收第三方 dll 返回的宽字节类型(如: C++ 的 wchar_t * 或者 LPWSTR 类型),使用 PAnsiChar 只能接收到第一个字符,如果需要获取完整的字符串内容,就我们需要自己处理。
处理的思路也很简单:
第一步:获取到字符串首字符的地址;
用 Cardinal 类型来接收字符串的首地址,为了方便理解,直接把 Cardinal 定义为 PWideChar 类型,如
type
PWideChar = Cardinal; { Inno doesn't have a pointer type, so we use a Cardinal instead }
第二步:获取字符串的长度;
通过调用 windows 系统 api 中的 lstrlenW() 方法来获取字符串的长度,返回类型也是 Cardinal:
{ This function allows us to get us the length of a string from a PWideChar }
function lstrlenW(lpString: PWideChar): Cardinal;
external 'lstrlenW@kernel32.dll stdcall';
第三步:生成一个长度为上述获取到的字符串长度的字符串变量;
通过 SetLength() 方法,设定字符串变量的长度;
第四步:把获取到的字符串的内容拷贝到这个新的字符串变量中;
通过调用 lstrcpyW() 方法:
{ This function copies a string - we declare it in such a way that we can pass a pointer
to an Inno string as destination
This works because Inno will actually pass a PWideChar that points to the start of the
string contents in memory, and internally the string is still null-terminated
We just have to make sure that the string already has the right size beforehand! }
function lstrcpyW_ToInnoString(lpStringDest: String; lpStringSrc: PWideChar): Integer;
external 'lstrcpyW@kernel32.dll stdcall';
实现例子:
[Code]
type
PWideChar = Cardinal; { Inno doesn't have a pointer type, so we use a Cardinal instead }
{ This function allows us to get us the length of a string from a PWideChar }
function lstrlenW(lpString: PWideChar): Cardinal;
external 'lstrlenW@kernel32.dll stdcall';
{ This function copies a string - we declare it in such a way that we can pass a pointer
to an Inno string as destination
This works because Inno will actually pass a PWideChar that points to the start of the
string contents in memory, and internally the string is still null-terminated
We just have to make sure that the string already has the right size beforehand! }
function lstrcpyW_ToInnoString(lpStringDest: String; lpStringSrc: PWideChar): Integer;
external 'lstrcpyW@kernel32.dll stdcall';
function GetStringFromPWideChar(pointer : PWideChar): String;
var
stringLength: Cardinal; { Length of the string we got }
innoString: String; { This is where we'll copy the string into }
begin
{ The pointer is actually just a renamed Cardinal at this point: }
Log('String pointer = ' + IntToStr(pointer));
{ Now we have to manually allocate a new Inno string with the right length and
copy the data into it }
{ Start by getting the string length }
stringLength := lstrlenW(pointer);
Log('String length = ' + IntToStr(stringLength));
{ Create a string with the right size }
innoString := '';
SetLength(innoString, stringLength);
{ This check is necessary because an empty Inno string would translate to a NULL pointer
and not a pointer to an empty string, and lstrcpyW cannot handle that. }
if StringLength > 0 then begin
{ Copy string contents from the external buffer to the Inno string }
lstrcpyW_ToInnoString(innoString, pointer);
end;
{ Now we have the value stored in a proper string variable! }
Log('String value = ' + innoString);
Result := innoString;
end;
这里通过 GetCommandLineW() 方法来测试
[code]
{ Example of a function that returns a PWideChar }
function GetCommandLineW(): PWideChar;
external 'GetCommandLineW@kernel32.dll stdcall';
function InitializeSetup(): Boolean;
var
returnedPointer: PWideChar; { This is what we get from the external function }
innoString : String;
begin
returnedPointer := GetCommandLineW();
innoString = GetStringFromPWideChar(returnedPointer);
Log('innoString is: ' + innoString);
end;
参考:
How can I dereference a pointer in Inno Setup Pascal Script?
可能有关: