Solved

Dynamically created Objects from DLL's

Posted on 1997-06-13
2
139 Views
Last Modified: 2010-04-06
G'Day,
  I'm having problems with dynamically allocated Objects being distroyed once the DLL is freed.

  I have a DLL which gets passed a TStringList as one of it's parameters.  I dynamically create objects (of type TObject) and add these to the Object Property of the TStringList using TStringList.AddObject.  I load in the DLL from the main application using LoadLibrary and free it using FreeLibrary.  Once I return from the DLL and free it, I can not access the Objects of the TStringList.  When I try to access the objects, I get an Access Violation.  From this I assume that the objects are being freed along with the DLL.

  I'm already using ShareMem in the DLL's Uses section and in my main application Uses section.  From what I've read about this, it allocates memory from the Global Heap thus giving other modules access to it but this is not what appears to be happening.

  What I need to know is if there is any way to create Objects in the DLL which the main application can gain access to after the DLL has been freed?

Note : It is not pratical to keep the DLL open until I exit the main application as I will have many DLL's loaded at the same time.

  Please Help.  Thanks.

0
Comment
Question by:Matho
2 Comments
 
LVL 2

Accepted Solution

by:
icampbe1 earned 100 total points
ID: 1337008
You dont say what what you're running D1, D2 D3?  I gather from your sharemem comment that its D2 or D3.
You dont say anything about the Constructor or Destructor of your objects.  If the object instance is a DLL global or not.  How do you do the add of the object??  StringList.AddObject( NewObj.Create )???

Without this info I can't be certain, but it shure looks like you destroyed the object instance by freeing the DLL.  The object pointer in the stringlist is no longer valid.  (I'm not telling you anything new by this).  My answer is you destroyed the object.

If you want, I'll look at the DLL code and help you with it (God knows I've been down this road many times before).

Ian C.
0
 

Author Comment

by:Matho
ID: 1337009
Thanks Ian,
  You are correct in your assumption, I'm using Delphi2.

  I'll try and explain what I'm doing...
The TFBClass and TUserLabelClass, described below, are both created inside the DLL. The TStringList inside TFBClass is used to hold the TLabelClass.  The TFBClass is held in a third Class which is passed to the DLL.  The third CLass is a global variable of the main application and is created on the Main Applications OnCreate.  The Class is of the following type.

type
  TMainClass = class(TObject)
    FBs : TStringList;
  public
    constructor Create;
  end;

The DLL code is something like this..  (Cut down version)

unit DLLFile;

interface

uses
  ShareMem, Windows, Messages, SysUtils, Classes, Graphics,  
  Controls, Forms,  Dialogs, StdCtrls;

type
  TMainClass = class(TObject)
    FBs : TStringList;     { TFBClass }
  public
    constructor Create;
  end;

type
  TFBClass = class(TObject)
    Name : string;
    Address : Integer;
    UserLabels : TStringList;           { TLabelClass }
  public
    constructor Create;
  end;

type
  TLabelClass = class(TObject)
    Name : string;
    Offset : Integer;
  end;

type
  TDLLForm = class(TForm)
    DoneButton: TButton;
    procedure DoneButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  DLLForm: TDLLForm;
  DeviceData : TMainClass;
  FB : TFBClass;

function ExecuteDLL(AOwner : TControl; var PData : Pointer):Pointer; stdcall;

implementation

{$R *.DFM}

constructor TMainClass.Create;
begin
  inherited Create;
  FBs := TStringList.Create;
end;

constructor TFBClass.Create;
begin
  inherited Create;
  UserLabels := TStringList.Create;
end;

{ This function is exported out of the DLL and is called from the main Application.  An explination of this is given after the DLL Code}

function ExecuteDLL(AOwner : TControl; var Data : TMainClass):Pointer; stdcall;
begin
  DLLForm := TButtonForm.Create(AOwner);
  DLLForm.SetBounds(AOwner.ClientOrigin.X,
    AOwner.ClientOrigin.Y,
    AOwner.Width,
    AOwner.Height);     {Deffining the bounds of the form}
  DeviceData := Data;  
  Result := ButtonForm;
end;

procedure TDLLForm.FormCreate(Sender: TObject);
var
  LabelName : TLabelClass;
begin
  FB := TFBClass.Create;
  FB.Name := 'Name';
  FB.Address := 35;
  LabelName := TLabelClass.Create;
  LabelName.Name := 'Fred';
  LabelName.Offset := 5;
  FB.UserLabels.AddObject(LabelName.Name,LabelName);
{ This is not exact code but it shows you what I'm doing }
end;

procedure TDLLForm.DoneButtonClick(Sender: TObject);
begin
  DeviceData.FBs.AddObject(FB.FBName,FB);
  Close;
end;

end.    //End of DLL Code

  In the ExecuteDLL function,  Data is the TMainClass to which the TFBClass is to be added.  The pointer that gets returned is assigned to a Form in the main Application and allows me to destroy the DLL  Form once I've finished with the DLL. i.e  In the Main Application I have..

procedure AddStuff;
var
  Child : TForm;
  MyHandle : THandle;
  ExecuteDLL : function(AOwner : TControl; var Data :
  TMainClass):Pointer; stdcall;
begin
  MyHandle := LoadLibrary(PChar(DLLName));
  @ExecuteDLL := GetProcAddress(MyHandle, 'ExecuteDLL');
  Child := ExecuteDLL(TControl(GroupBox), Data);
  Child.ShowModal;                                          
  Child.Free;
  FreeLibrary(MyHandle);
end;

Data is a global variable of type TMainClass and has already been created.  DLLName is the DLL Name.

  I hope this explains things.  As for Destructors for the objects,
I'm not really worried about freeing them up as yet.  I can always
add these later when I have the program working.  I'm more
interested in getting the Objects passed back to the Main
Application.   Thanks again.

0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

806 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question