Unloading Delphi dll

Unloading Delphi dll

Anonymous
Not applicable
1,610 Views
6 Replies
Message 1 of 7

Unloading Delphi dll

Anonymous
Not applicable
Set obj = New MyProj.MyClass ' calls initialize
Set obj = Nothing ' calls destructor

How can I call the destructor from within the dll without causing an Access
Violation (free does this)
ie when the user closes the form AutoCAD unloads dll (the vba Set
obj=Nothing destroys the form prematurely)
0 Likes
1,611 Views
6 Replies
Replies (6)
Message 2 of 7

Anonymous
Not applicable
Can you describe in more detail how your project is
structured?

"Joe Parker" wrote in message
news:97CCFD0A463E866E2E8549D6848257CB@in.WebX.maYIadrTaRb...
>
> Set obj = New MyProj.MyClass ' calls initialize
> Set obj = Nothing ' calls destructor
>
> How can I call the destructor from within the dll without causing an
Access
> Violation (free does this)
> ie when the user closes the form AutoCAD unloads dll (the vba Set
> obj=Nothing destroys the form prematurely)
>
>
0 Likes
Message 3 of 7

Anonymous
Not applicable
my automation object basically calls a form as follows. The form does a load
of stuff independant of AutoCAD and has an Ok button that closes the form
when the user is finished. I want the destructor to be called at this stage
but I get Access Violation if I try to free anywhere in this unit.

Question 2: Why does (ExtractFileName(Application.EXEName)='ACAD.EXE') (only
on some systems) return false when called from inside my Delphi dll writtrn
for AutoCAD

unit AcForm_IMPL;

interface

uses
ComObj, ActiveX, Windows, AcForm_TLB, StdVcl, Main_Form,AutoCAD_TLB;

type
TTest = class(TAutoObject, ITest)
private
FForm1: TForm1;
Acad:AcadApplication;
protected
function Get_Visible: WordBool; safecall;
procedure Set_Visible(Value: WordBool); safecall;
procedure GetApplication(const _Acad: IDispatch); safecall;
{ Protected declarations }
public
Procedure Initialize; override;
Destructor Destroy; override;
end;

implementation

uses ComServ;

procedure TTest.Initialize;
begin
Inherited Initialize;
FForm1 := TForm1.Create(nil);
end;

destructor TTest.Destroy;
begin
FForm1.Free;
inherited destroy;
end;

function TTest.Get_Visible: WordBool;
begin
Result := FForm1.Visible;
end;

procedure TTest.Set_Visible(Value: WordBool);
begin
FForm1.Visible := Value;
end;

procedure TTest.GetApplication(const _Acad: IDispatch);
begin
Acad:=_Acad as AcadApplication;
FForm1.Acad:=Acad;
end;

initialization
TAutoObjectFactory.Create(ComServer, TTest, Class_Test,
ciMultiInstance, tmApartment);
end.


"Tony Tanzillo" wrote in message
news:3454CD0B9515F6E88B4610C82B78BAC0@in.WebX.maYIadrTaRb...
> Can you describe in more detail how your project is
> structured?
>
> "Joe Parker" wrote in message
> news:97CCFD0A463E866E2E8549D6848257CB@in.WebX.maYIadrTaRb...
> >
> > Set obj = New MyProj.MyClass ' calls initialize
> > Set obj = Nothing ' calls destructor
> >
> > How can I call the destructor from within the dll without causing an
> Access
> > Violation (free does this)
> > ie when the user closes the form AutoCAD unloads dll (the vba Set
> > obj=Nothing destroys the form prematurely)
> >
> >
>
>
0 Likes
Message 4 of 7

Anonymous
Not applicable
"Joe Parker" wrote in message
news:19E2A941B6B7FAE93A1BA1E4D916AF94@in.WebX.maYIadrTaRb...
> my automation object basically calls a form as follows. The form does a
load
> of stuff independant of AutoCAD and has an Ok button that closes the form
> when the user is finished. I want the destructor to be called at this
stage...

Revise your ActiveX server to eliminate the Visible
property and just expose a single method called Show():

Procedure TTest.Show
var
Form1: TForm1;
begin
Form1 := TForm1.Create(nil);
try
Form1.ShowModal;
finally
Form1.Free;
end;
end;

Using the above method, the form is created, shown, and
destroyed each time you use it from the client.

> Question 2: Why does (ExtractFileName(Application.EXEName)='ACAD.EXE')
(only
> on some systems) return false when called from inside my Delphi dll
writtrn
> for AutoCAD

If this is an ActiveX DLL than you shouldn't be using
Application.ExeName. What is it you're trying to get
(the name of the ActiveX .dll, something else)?
0 Likes
Message 5 of 7

Anonymous
Not applicable
thanks for the reply tony

1. I was hoping not to ShowModal as I want the user to be able to interact
with Acad. I only want the Automation Object destroyed if the Ok button is
selected

2.My main form can be a stand alone application where
ExtractFileName(Application.EXEName) returns the name of my application (in
my case HollowCore)
or it is called by an Automation Object (built in a dll called by AutoCAD)
where
(ExtractFileName(Application.EXEName) returns 'ACAD.EXE' (on most systems)
depending on the result of the function I dress up the form in different
ways
I suppose what I want to do is know is whether the form is operating from
inside a dll or is it the main form of a standalone application


"Tony Tanzillo" wrote in message
news:02AB8423FE6463F9A0BDA1BBBFF6C307@in.WebX.maYIadrTaRb...
> "Joe Parker" wrote in message
> news:19E2A941B6B7FAE93A1BA1E4D916AF94@in.WebX.maYIadrTaRb...
> > my automation object basically calls a form as follows. The form does a
> load
> > of stuff independant of AutoCAD and has an Ok button that closes the
form
> > when the user is finished. I want the destructor to be called at this
> stage...
>
> Revise your ActiveX server to eliminate the Visible
> property and just expose a single method called Show():
>
> Procedure TTest.Show
> var
> Form1: TForm1;
> begin
> Form1 := TForm1.Create(nil);
> try
> Form1.ShowModal;
> finally
> Form1.Free;
> end;
> end;
>
> Using the above method, the form is created, shown, and
> destroyed each time you use it from the client.
>
> > Question 2: Why does (ExtractFileName(Application.EXEName)='ACAD.EXE')
> (only
> > on some systems) return false when called from inside my Delphi dll
> writtrn
> > for AutoCAD
>
> If this is an ActiveX DLL than you shouldn't be using
> Application.ExeName. What is it you're trying to get
> (the name of the ActiveX .dll, something else)?
>
>
>
>
0 Likes
Message 6 of 7

Anonymous
Not applicable
"Joe Parker" wrote in message

See below for some comments on using modeless
Delphi forms in AutoCAD.

> 1. I was hoping not to ShowModal as I want the
> user to be able to interact with Acad. I only
> want the Automation Object destroyed if the Ok
> button is selected

You cannot destroy your ActiveX object, as long as
there is one or more references to it in the VBA
client. This is what's causing the AV. You have
to keep in mind that a COM object's lifetime is
controlled by its clients. As long as one or more
clients holds a reference to your COM object, you
cannot destroy it.

To get around this, you can do the following:

In your form, declare a public property of type
IUnknown, and a private variable of the same
type:

type
TForm1 = class(TForm)
private
FCOMObject: IUnknown;
//.....
public
Property ComObject: IUnknown read FCOMObject write FCOMObject;
//...
end;

In your COM object's Initialize() method:

procedure TTest.Initialize;
begin
Inherited Initialize;
FForm1 := TForm1.Create(nil);
// Let the form keep a reference to this COM object
FForm1.ComObject := Self As IUnknown;
end;

Then, add an OnClose handler to your form, and
in it, set the CloseAction to caHide, and release
the COM object:

TForm1.OnClose((Sender: TObject; var Action: TCloseAction);
begin
CloseAction := caHide;
FComObject := Nil;
end;

> I suppose what I want to do is know is whether the form is operating from
> inside a dll or is it the main form of a standalone application

Just call IsLibrary() and if it returns True, then
you are running in a .DLL.

Some comments on using modeless Delphi forms in AutoCAD:

Without some extensive programming, using a Delphi Form
modelessly in AutoCAD will not work entirely as expected.
The reason for this is because much of the functionality
that Delphi forms and controls implement are dependent
on the Delphi Application object (TApplication) having a
message pump, which is not the case when your form runs
in a non-Delphi host.

For example, when your form is shown modelessly in the
ActiveX dll, you will note that you can't use the TAB
key to advance focus from one control to the next. A
number of other things will not work correctly also.

I have a solution for this, but I will need to package
it up in a form that you can use. I developed a special
Delphi form class called TAcadForm, which is derived
from Delphi's TForm, and is "AutoCAD aware". IOW, it
will function properly as a modeless form when used in
AutoCAD's process.

I will need some time to put in a package along with
any other required units, and once I do, I'll post it
on my web page.
0 Likes
Message 7 of 7

Anonymous
Not applicable
Excellent, thx
"Tony Tanzillo" wrote in message
news:B5B2E11D0AA6F623A2E7A0891EFD73C7@in.WebX.maYIadrTaRb...
> "Joe Parker" wrote in message
>
> See below for some comments on using modeless
> Delphi forms in AutoCAD.
>
> > 1. I was hoping not to ShowModal as I want the
> > user to be able to interact with Acad. I only
> > want the Automation Object destroyed if the Ok
> > button is selected
>
> You cannot destroy your ActiveX object, as long as
> there is one or more references to it in the VBA
> client. This is what's causing the AV. You have
> to keep in mind that a COM object's lifetime is
> controlled by its clients. As long as one or more
> clients holds a reference to your COM object, you
> cannot destroy it.
>
> To get around this, you can do the following:
>
> In your form, declare a public property of type
> IUnknown, and a private variable of the same
> type:
>
> type
> TForm1 = class(TForm)
> private
> FCOMObject: IUnknown;
> //.....
> public
> Property ComObject: IUnknown read FCOMObject write FCOMObject;
> //...
> end;
>
> In your COM object's Initialize() method:
>
> procedure TTest.Initialize;
> begin
> Inherited Initialize;
> FForm1 := TForm1.Create(nil);
> // Let the form keep a reference to this COM object
> FForm1.ComObject := Self As IUnknown;
> end;
>
> Then, add an OnClose handler to your form, and
> in it, set the CloseAction to caHide, and release
> the COM object:
>
> TForm1.OnClose((Sender: TObject; var Action: TCloseAction);
> begin
> CloseAction := caHide;
> FComObject := Nil;
> end;
>
> > I suppose what I want to do is know is whether the form is operating
from
> > inside a dll or is it the main form of a standalone application
>
> Just call IsLibrary() and if it returns True, then
> you are running in a .DLL.
>
> Some comments on using modeless Delphi forms in AutoCAD:
>
> Without some extensive programming, using a Delphi Form
> modelessly in AutoCAD will not work entirely as expected.
> The reason for this is because much of the functionality
> that Delphi forms and controls implement are dependent
> on the Delphi Application object (TApplication) having a
> message pump, which is not the case when your form runs
> in a non-Delphi host.
>
> For example, when your form is shown modelessly in the
> ActiveX dll, you will note that you can't use the TAB
> key to advance focus from one control to the next. A
> number of other things will not work correctly also.
>
> I have a solution for this, but I will need to package
> it up in a form that you can use. I developed a special
> Delphi form class called TAcadForm, which is derived
> from Delphi's TForm, and is "AutoCAD aware". IOW, it
> will function properly as a modeless form when used in
> AutoCAD's process.
>
> I will need some time to put in a package along with
> any other required units, and once I do, I'll post it
> on my web page.
>
>
>
>
0 Likes