Jump to content
FabDev

Dynamic BPL loading (CData)

Recommended Posts

Hello,

 

I have tested CData components (Free with Delphi Enterprise version). It's is a very interesting components set : All API, Webservice become "Table and queries".

But I have a problem if you integrate the component to open Excel file your executable is increased by  14 MB  !

I need to add 5 or 10 CData components (like Excel, Excel Online, FTP etc.). After this the executable size do more than 100 MB. With runtime library it's the same problem.

The customers of my software don't need to use all components each time. So I would like to dynamically load the BPL file using LoadPackage when needed.

To do this I use I try to use LoadPackage like this :

 

 

procedure TForm10.Button1Click(Sender: TObject);
var
  PackageModule: HModule;
  AClass: TPersistentClass;
begin
  PackageModule := LoadPackage('CData.Excel.D26.bpl');
  if PackageModule <> 0 then
  begin
    AClass := GetClass('TFDPhysCDataExcelDriverLink');//    no effect with ('TFDPhysCDataExcelDriver');

    if AClass <> nil then
    begin
      with TComponentClass(AClass).Create(Application)
        as TFDPhysCDataExcelDriverLink do
      begin
        create(self);

      // FDPhysManager().RegisterDriverClass(TFDPhysCDataExcelDriverLink);
       // FDConnection1.Name := 'SQLTest';
        FDPhysManager().RegisterRDBMSKind(cDBMSKindCData, S_CData_DriverID);
       // FDPhysManager().RegisterDriverClass(TFDPhysCDataExcelDriverLink);
        FDConnection1.DriverName := 'CData.Excel';
        with FDConnection1.Params as TFDConnectionDefParamsClass do begin
           add('File=C:\MyExcelWorkbooks\SampleWorkbook.xlsx');
        end;

        FDQuery1.SQL.clear;
        FDQuery1.SQL.add('SELECT * FROM Sheet WHERE FirstName = ''Bob''');
        FDQuery1.ExecSQL;


        Free;
      end;
    end
    else   showmessage('error');

    UnloadPackage(PackageModule);
  end;
end;

Initialization
 RegisterClass(TFDPhysCDataExcelDriverLink);
// RegisterClass(TFDPhysCDataExcelDriver);
end.

 

But at line "FDQuery1.ExecSQL;" I get this error "[Firedac][Phys]-300 Driver [CData.Excel] is not registered. Correct The ID of the driver or define the virtual drivers [CDATA.Excel] in FDDrivers.ini".

Certainly because a line like this is missing :

FDPhysManager().RegisterDriverClass(TFDPhysCDataExcelDriver);

 

But I don't know how to dynamically Register a driver class to Firedac !

 

Any idea ? (Full source in attachment)

 

 

 

DynamicBPLExcel.zip

Share this post


Link to post

You said:

    if AClass <> nil then
    begin
      with TComponentClass(AClass).Create(Application)
        as TFDPhysCDataExcelDriverLink do
      begin
        create(self);

 

but I'm curious why you're calling create(self) when the context is already operating on a newly created instance?

 

You seem to be creating an instance of something, then casting it into a (probably much larger) object and then recreating it.
 

something := TFDPhysCDataExcelDriverLink( TComponentClass(AClass).Create(Application) ).Create(self);

 

This does not look kosher to me.

 

Edited by David Schwartz

Share this post


Link to post
10 hours ago, David Schwartz said:

something := TFDPhysCDataExcelDriverLink( TComponentClass(AClass).Create(Application) ).Create(self);

 

 

 

 

Yes it's better to avoid ambiguity of "Self" but in this case by default Delphi seems to consider (Self=Form10).

 

But I think that it miss something like (done in initialization of unit FireDAC.Phys.CDataExcel.pas) :

 FDPhysManager().RegisterDriverClass(TFDPhysCDataExcelDriver);

 

But :

  AClass2  := GetClass('TFDPhysCDataExcelDriver');

Return nil...

 

 

Edited by FabDev

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×