I need to return a string value to the calling inno setup script. Problem is I can't find a way to manage the allocated memory. If I allocate on the DLL side, I don't have anything to deallocate with on the script side. I can't use an output parameter, because there is no allocation function in the Pascal Script either. What should I do?
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
Here is a sample code of how to allocate a string that returns from a DLL:
[Code]
Function GetClassNameA(hWnd: Integer; lpClassName: PChar; nMaxCount: Integer): Integer;
External 'GetClassNameA@User32.dll StdCall';
function GetClassName(hWnd: Integer): string;
var
ClassName: String;
Ret: Integer;
begin
{ allocate enough memory (pascal script will deallocate the string) }
SetLength(ClassName, 256);
{ the DLL returns the number of characters copied to the buffer }
Ret := GetClassNameA(hWnd, PChar(ClassName), 256);
{ adjust new size }
Result := Copy(ClassName, 1 , Ret);
end;
回答2:
A very simple solution for the case where the DLL function is called only once in the installation - use a global buffer in your dll for the string.
DLL side:
char g_myFuncResult[256];
extern "C" __declspec(dllexport) const char* MyFunc()
{
doSomeStuff(g_myFuncResult); // This part varies depending on myFunc's purpose
return g_myFuncResult;
}
Inno-Setup side:
function MyFunc: PChar;
external 'MyFunc@files:mydll.dll cdecl';
回答3:
The only practical way to do this is to allocate a string in Inno Setup, and pass a pointer to that along with the length to your DLL that then writes to it up to the length value before returning.
Here's some example code taken from the newsgroup.
function GetWindowsDirectoryA(Buffer: AnsiString; Size: Cardinal): Cardinal;
external 'GetWindowsDirectoryA@kernel32.dll stdcall';
function GetWindowsDirectoryW(Buffer: String; Size: Cardinal): Cardinal;
external 'GetWindowsDirectoryW@kernel32.dll stdcall';
function NextButtonClick(CurPage: Integer): Boolean;
var
BufferA: AnsiString;
BufferW: String;
begin
SetLength(BufferA, 256);
SetLength(BufferA, GetWindowsDirectoryA(BufferA, 256));
MsgBox(BufferA, mbInformation, mb_Ok);
SetLength(BufferW, 256);
SetLength(BufferW, GetWindowsDirectoryW(BufferW, 256));
MsgBox(BufferW, mbInformation, mb_Ok);
end;
Also see this thread for more up to date discussion.