• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 809
  • Last Modified:

Dynamic package loading

Is there a way to get hold of a function in a package the same way as with .dll's (GetProcAddress). The thing is that I'd like to have a base class say TMyBase. In the application I'd like to load components dynamically so I dont know the name of the main class in the components. The component's main class inherits from TMyBase and implements a function <function GetMainClass : TMyBase>. When the application starts loading components I'd like it to work like this

     TGetMainClass = function(....) : TMyBaseClass;
     ....

> OnCreate-------
  var
      aGetMainClass : TGetMainClass;
  begin
     for i:=0 to myPackageList.count-1 do
     begin
          myPackageList[i].itsHandle := LoadPackage(myPackageList[i].itsName);
          @aGetMainClass := GetProcAddress(myPackageList[i].itsHandle, 'GetMainClass');
          myPackageList[i].itsMainClass := aGetMainClass(..)
     end;

This way I can read the settings in the registry file to obtain the components installed and easely install a new component without recompiling the application.

The problem I have is that @aGetMAinClass returns nil?  
0
peed112097
Asked:
peed112097
  • 3
  • 2
1 Solution
 
Hagen040798Commented:
Hi

Your write this code in the External-Package

inialization
  RegisterClasses([TMyClass]);
finalization
  UnregisterClasses([TMyClass]);
end.

Then Your load the external-Package with LoadPackage, the initialization Section from all units in the Packages will called and so register the TMyClass. Now You can acces with GetClass('TMyClass') = TMyClass also GetClass('TMyClass').Create ..... and so on.

Hagen.
0
 
peed112097Author Commented:
OK, but where do I put the
inialization , finalization code? Is it in the package file?
0
 
peed112097Author Commented:
I also can't figure out how to gegister the class. Do I have to typecast the class name to TPersistantClass?
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
Hagen040798Commented:
Hi peed, here a short Example with separate Registration.

unit RegClass;
{this unit handled the Registration from the Classes.
 this unit must pack in a package to acces from the external Modules
 to Examples this unit in Main.dpl}
interface

uses Classes;

{register Classes}
procedure RegisterModuleClasses(const Classes: Array of TClass);
{unregister Classes}
procedure UnregisterModuleClasses(const Classes: Array of TClass);
{get back a registered Class with the specific ClassName}
function GetModuleClass(const ClassName: String): TClass;
{get back the List of registered Classes}
function ModuleClassList: TStrings;

implementation

const
  FList: TStringList = nil;

function ModuleClassList: TStrings;
begin
  if FList = nil then
  begin
    FList := TStringList.Create;
    FList.Sorted := True;
    FList.Duplicates := dupIgnore;
  end;
  Result := FList;
end;

procedure RegisterModuleClasses(const Classes: Array of TClass);
var
  I: Integer;
begin
  for I := Low(Classes) to High(Classes) do
    if Classes[I] <> nil then ModuleClassList.AddObject(Classes[I].ClassName, Classes[I]);
end;

procedure UnregisterModuleClasses(const Classes: Array of TClass);
var
  I,J: Integer;
begin
  for I := Low(Classes) to High(Classes) do
    if Classes[I] <> nil then
    begin
      J := ModuleClassList.IndexOf(Classes[I]);
      if J >= 0 then ModuleClassList.Delete(J);
    end;
end;

function GetModuleClass(const ClassName: String): TClass;
begin
  I := ModuleClassList.IndexOf(ClassName);
  if I >= 0 then Result := ModuleClassList.Objects[I]
    else Result := nil;
end;

initialization
finalization
  FList.Free;
  FList := nil;
end.

{-------------------}
unit MyTestModules;

{this Unit pack in a external Package or Library, add the packgage with included RegClass,
 and compile with the Package-option
 to Example this unit in MyModule.dpl and add Main (Main.dpl) in Projectoptins\Packages}

interface

uses Classes, ....;

type
  TMyClass = class(from TXYZObject)
    procedure XYZ;
  end;

implementation

uses RegClass;

procedure TMyClass.XYZ;
begin
{....}
end;

initialization
  RegisterModuleClasses([TMyClass]);
finalization
  UnRegisterModuleClasses([TMyClass]);
end.

{-----------------------------}
unit MainTest;

{This unit is the Application-unit}

interface

uses RegClass;

type
  TmyForm = class(TForm)
    function LoadAndCreateMyClass: TObject;
  end;

implementation

function TMyForm.LoadAndCreateMyClass: TObject;
var
  Module: hModule;
  C: TClass;
begin
  Result := nil;
  Module := LoadPackage('MyModule.dpl');
{when load a package or library then was called all initialization-Section from the
 contained Units, in this Sections you must call RegisterModuleClasses and after
 the loading you can access to the registered classes with GetModuleClass per Name, yust here}
  C := GetModuleClass('TMyClass');
  if C <> nil then Result := C.Create {create the Object}
    else UnloadPackage(Module); {unload the Package, Class was not registered}
end;

{I hope that help Your.
 When you has Questions then post me Your E-Mail-address and i make a Example for you or i send
 Your my Project from my Firma. This is very better and complex.
 The best Way is you define a Basisclass with defined interface-function's, in my Firma we
 use a Descend from TForm with a function to Exchange Datas from the Form, all ModuleForms
 used the BaseFormClass. The Implementaion from this BaseForm is placed in RegClass.
 We have also Formular's in DLL's and loading this dynamicly at Runtime and Unloading when the
 Form is destroyed.

 Sorry for my english. Hagen }

end.




0
 
Hagen040798Commented:
Hi peed

The initialization and finalization Sections placed in units at last not in the Package-Project-File (in *.pas not in *.dpr). This sections initialize the Unit and finalize the Units. A Package-DLL export two function's "Initialize" and "Finalize" this calls all initialization and finalization -Section's all units contained in a Package, in my Firma we use not Packages but Library's this is better.
When your not will use RegisterClasses from Classes you can write functions the Register other Classes.
to Example:

type
  TMyClass = class of TMyObject;
  TMyObject = class(TObject)
  end;


function RegisterMyClass(const Classes: array of TMyClass);


Hagen.
0
 
ekoindriCommented:
not work in delphi 2007 + vista
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now