[Lazarus] Library, Threads and Gui

Kostas Michalopoulos badsectoracula at gmail.com
Tue Jun 5 16:02:30 CEST 2012


On 5/6/2012 9:29 πμ, Mattias Gaertner wrote:
> The "is" operator requires that the library uses the VMTs of the main 
> application.
What does that imply exactly? I made a quick app to test the possibility 
of using DLLs for plugins. Both the app and the DLL uses a unit that 
contains the following class:

TGBrush = class(TComponent)
protected
function GetBrushEditor: TWinControl; virtual; abstract;
function GetName: string; virtual; abstract;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Push(ACanvas: TCanvas; X, Y: Integer); virtual;
procedure Release(ACanvas: TCanvas; X, Y: Integer); virtual;
procedure Draw(ACanvas: TCanvas; X1, Y1, X2, Y2: Integer); virtual; 
abstract;
property BrushEditor: TWinControl read GetBrushEditor;
property Name: string read GetName;
end;

And also another class that contains a list with TGBrush objects like 
the above. These objects access both a TCanvas from the main application 
and will return a TWinControl descendant (most likely, but not 
necessarily, a TFrame designed in Lazarus) created by the DLL that will 
be embedded in a TPanel in the main application.

When adding a new object i use the "is" operator to see if it is a 
descendant of TGBrush and this always fails. My current setup is to pass 
the memory manager of the application and the shared brushes object to 
the library:

var
MemMgr: TMemoryManager

GetMemoryManager(MemMgr);
RegProc:=TGBrushDLLRegisterProc(GetProcedureAddress(Lib, 
'BrushDLLRegister'));
if Assigned(RegProc) then RegProc(MemMgr, GBrushes);

And from the DLL side use the memory manager as the first thing and call 
Application.Initialize:

procedure BrushDLLRegister(const AppMemoryManager: TMemoryManager; 
GBrushes: TGBrushes);
begin
SetMemoryManager(AppMemoryManager);

// The call to Application.Initialize is made because i read
// in the forums that it is needed from libraries to "sync"
// the two instances together
Application.Initialize;

// here the TGBrush constructor checks if its owner is a
// TGBrushes descendant using the "is" operator and fails
TSprayGBrush.Create(GBrushes);
end;

Why exactly the "is" operator fails and how can it be fixed? And how 
will all the above work under Windows, Linux and Mac OS X?

If needed i can put somewhere the full program i used for testing, but i 
think the above shows what i'm trying to do.

Kostas "Bad Sector" Michalopoulos





More information about the Lazarus mailing list