jrsoftware.org // Jordan Russell's Software
-Home

Products

-Inno Setup


-Toolbar2000

-Toolbar97

-StripReloc

-More...

Support

-Newsgroups

-Contact Me

#######
visitors since
Jan. 1998

Inno Setup Knowledge Base
Return to index

HOWTO: Return string list from a DLL

Article Created: 2006-01-18 18:18 GMT by Jordan Russell
Last Updated: 2006-01-18 19:44 GMT by Jordan Russell


When a need arises to return a list of strings from a DLL, your first instinct may be to create a function with a prototype like the following:

function FunctionThatReturnsStrings: TStringList;

On the Inno Setup side, however, when you attempt to call methods or access properties on the returned TStringList instance, it crashes. Why?

Sharing a Delphi class between different modules is illegal. There are two primary reasons for this:

  • If the modules were compiled with different versions of Delphi (which is quite likely to be the case; Inno Setup is compiled in Delphi 2), the class's properties, fields, and virtual methods may be located at different offsets. For example, Delphi 7's TStringList stores its Count property at offset $14, but Delphi 2 expects to find it at offset $10.
  • In Delphi, each module has its own heap. If a module attempts to free memory allocated by another, an exception will be raised. One way this can happen is if you call a method that returns a String. The callee will allocate the string, but it is the caller that will try to free it.

This problem can be worked around by converting the list of strings to a type that isn't a class and doesn't require freeing: a PChar.

On the DLL side:

library TheDLL;

uses
  SysUtils,
  Classes;

var
  { This must be a global variable so it's preserved in memory after the
    FunctionThatReturnsStrings function exits }
  ReturnedString: String;

function FunctionThatReturnsStrings: PChar; stdcall;
var
  S: TStringList;
begin
  S := TStringList.Create;
  S.Add('aaaa');
  S.Add('bbbb');
  S.Add('cccc');
  ReturnedString := S.Text;
  Result := PChar(ReturnedString);
end;

exports
  FunctionThatReturnsStrings;

end.

On the Inno Setup side:

[Files]
Source: "TheDLL.dll"; Flags: dontcopy

[Code]
function FunctionThatReturnsStrings: PChar;
  external 'FunctionThatReturnsStrings@files:TheDLL.dll stdcall';

function InitializeSetup: Boolean;
var
  S: TStringList;
  I: Integer;
begin
  S := TStringList.Create;
  try
    { Call the function, and extract the strings from the PChar result }
    S.Text := FunctionThatReturnsStrings;

    { Show each of the strings in a message box }
    for I := 0 to S.Count-1 do
      MsgBox(S[I], mbInformation, MB_OK);
  finally
    S.Free;
  end;
  
  Result := True;
end;

Site contents Copyright © 1997-2012 Jordan Russell. All rights reserved.