Page 1 of 1

Error when updating a field in a Shared-Mem-Application

Posted: Tue 01 Oct 2013 12:55
by Codehunter
Hello!

I'm want to write a new DLL-based application which has the TUniConnection on the Application.Mainform and the TUniTable (or Query and so on) on a form that resides in a dynamically loaded DLL. The UniConnection on the Mainfrom will be shared via FastMM4 to the DLL. The goal is an data-aware application with a central defined DB connection and some modules that using the existing DB connection to work with the DB.

This works good for a short time: Application starts, creates the child form in the DLL, assigns TUniTable.Connection at Runtime to the object on the Mainform and sets TUniTable.Active to TRUE. The Data from the assigned Table in the Database is displayed correctly in a attached TDBGrid. So i can say, data loading from the DB and the memory sharing between Mainform and DLL-Childform works fine.

But, unfortunately, when i'm edit an Record in the Grid, press Enter and try to change the active record, an Message "Cant assign TUniEncryption to TUniEncryption" appears. The modified data will not be written to the DB and after closing the application, much memory leaks (related to TUniConnection) are reported.

Is this application design generally wrong for UniDAC? Should i use a separate TUniConnection for each DLL-Childform? But in this case, one application instance does open multiple DB sessions. I think, this is not a good design.

Thanks for any suggestion.
Cody

Re: Error when updating a field in a Shared-Mem-Application

Posted: Wed 02 Oct 2013 12:05
by AlexP
Hello,

You can use the same connection in the main application and DLL. But since we use the is operator to check type match when assigning objects, and the hierarchy of classes is different in the main application and DLL, you should build your application and DLL with the enabled Build With Runtime packages option. In this case, the application and DLL will use the same bpl - and there will be no problems.

Re: Error when updating a field in a Shared-Mem-Application

Posted: Sat 05 Oct 2013 06:15
by rxertxer
Hi I am using a trial components. I have tried to reproduce this issue and solution, but problem still occured. Also with FastMM4 or without.

COMMON INTERFACE UNIT for DLL and HostApp

Code: Select all

unit u_baseplugin_intf;

interface

uses Uni, Data.DB;

type
  IBasePluginInterface = interface(IInterface)
  ['{060A9C46-B3CF-4BA4-B025-2DC1D9F45076}']
  function GetPluginName: string;
  procedure SetConn(sConn:TUniConnection);
  procedure showF;

  property PluginName: string read GetPluginName;
  property Connection : TUniConnection write SetConn;
  end;

implementation

end.
HOST APP

Code: Select all

type
  TPluginInterface = function:IBasePluginInterface; stdcall;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var aPluginIntf : IBasePluginInterface;
    dllHandle : cardinal;

procedure LoadPlugin( aPlugin : pWideChar );
var
   lPlugin : TPluginInterface;
 begin
   dllHandle := LoadLibrary(aPlugin) ;
   if dllHandle <> 0 then
   begin
     @lPlugin := GetProcAddress(dllHandle, 'LoadPlugin') ;
     if Assigned (lPlugin) then
        begin
          aPluginIntf := lPlugin //call the function
          Label1.Caption:=aPluginIntf.PluginName;
          aPluginIntf.Connection:=UniConnection1;
          aPluginIntf.ShowF;
        end;
     else
      begin
        ShowMessage('LoadPlugin function not found') ;
        FreeLibrary(dllHandle) ;
      end;
   end
   else
   begin
     ShowMessage(aPlugin+' not found / not loaded') ;
   end;
 end;

procedure TForm1.LoadClick(Sender: TObject);
begin
  LoadPlugin('profileslist.dll');
end;

procedure TForm1.UnLoadClick(Sender: TObject);
begin
  aPluginIntf.Connection:=nil;
  aPluginIntf:=nil;
  FreeLibrary(dllHandle)
end;

DLL Main code

Code: Select all

library profileslist;

uses
  System.SysUtils,
  System.Classes,
  u_baseplugin_intf,
  u_profileslist in 'u_profileslist.pas' {Form_ProfilesList};

{$R *.res}

function LoadPlugin:IBasePluginInterface;
begin
  result:=TForm_ProfilesList.Create(nil);
end;

exports
  LoadPlugin;

begin
end.
DLL Form unit

Code: Select all

unit u_profileslist;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids, Vcl.DBGrids,  Vcl.StdCtrls,
  u_baseplugin_intf,
  Data.DB, DBAccess, Uni, MemDS;

type
  TForm_ProfilesList = class(TForm, IBasePluginInterface)
    DBGrid1: TDBGrid;
    UniTable1: TUniTable;
    UniDataSource1: TUniDataSource;
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    function GetPluginName: string;
    procedure SetConn(sConn:TUniConnection);
    { Private declarations }
  public
    procedure ShowF;
    { Public declarations }
  end;

var
  Form_ProfilesList: TForm_ProfilesList;

implementation

{$R *.dfm}

function TForm_ProfilesList.GetPluginName;
begin
  Result := 'List of profiles';
end;

procedure TForm_ProfilesList.SetConn(sConn: TUniConnection);
begin
  UniTable1.Connection:=sConn;
end;

procedure TForm_ProfilesList.ShowF;
begin
  ShowModal;
end;

procedure TForm_ProfilesList.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  UniTable1.Active:=false;
end;

procedure TForm_ProfilesList.FormShow(Sender: TObject);
begin
  UniTable1.Active:=true;
end;

end.

Re: Error when updating a field in a Shared-Mem-Application

Posted: Mon 07 Oct 2013 12:08
by AlexP
Hello,

Independently on whether you use one and the same module with interface or not, you should enable the 'Build With Runtime packages' option, in order to work with the same UniConnection in the main application and DLL. This not our restriction - the same situation occurs on an attempt to work wit any objects.