How to return a string from a DLL to Inno Setup?

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 '[email protected] 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;

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';

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 '[email protected] stdcall';
function GetWindowsDirectoryW(Buffer: String; Size: Cardinal): Cardinal;
external '[email protected] 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.