Board index » delphi » Object Pointer Problem

Object Pointer Problem

I would like to be able to override certain
interrupts within my turbo vision apps. The problem
arises when I have something like this.

AObject = object(TObject)
  Timer : LongInt;
  Procedure NewTimer; virtual;
  Procedure HookTimer; virtual;
 End;

Procedure AObject.NewTimer;
Begin
  Inc(Timer);
End;

Procedure AObject.HookTimer; virtual;
Begin
  SetIntVec($1C, @NewTimer);
End;

The SetIntVec returns a compiler error. Apparently I can't address a virtual procedure
using the @. I get an invalid procedure or function error. So, how do I get a pointer
to a virtual procedure?

 

Re:Object Pointer Problem


Quote
In article <31D2195E.1...@saltair.com> Scott Serven wrote:
>I would like to be able to override certain
>interrupts within my turbo vision apps. The problem
>arises when I have something like this.

>AObject = object(TObject)
>  Timer : LongInt;
>  Procedure NewTimer; virtual;
>  Procedure HookTimer; virtual;
> End;

>Procedure AObject.NewTimer;
>Begin
>  Inc(Timer);
>End;

>Procedure AObject.HookTimer; virtual;
>Begin
>  SetIntVec($1C, @NewTimer);
>End;

>The SetIntVec returns a compiler error. Apparently I can't address avirtual procedure
>using the @. I get an invalid procedure or function error. So, how do I geta pointer
>to a virtual procedu

Scott, I think you're trying to shoot yourself in the foot.  I assume that
the interrupts chain.  So A takes the interrupt, then b takes the interrupt
and chains to A.  When A is disposed B will continue to chain to the now
non-existent location -- BANG!

Think about using one static handler, possibly a descendant of tCollection
that calls each registered timer object's handler method then chains to the
original interrupt handler.  The constructor or function that initializes
your timer objects should register (insert) the object with the handler.  
Likewise the destructors should remove itself from the handler's list.  An
alternative is not to dispose of the object directly but by using
Handler^.Free(TimerObject).

I use a similar method for managing objects that need to clean up after
themselves even if the program abends.  During the program's initialization
a global "OnExit" tCollection is initialized.  As critical objects are
constructed, they are inserted into OnExit.  When they have finished they
are disposed using OnExit^.Free( pInstance );  The exit routine disposes
OnExit, which by definition disposes each object which gives then a chance
to flush, close, and erase files as necessary.

--
RDon...@gnn.com
http://members.gnn.com/rdonais/index.html
-------------------------------------------
Knowledge is one of the few things that you
can give away and still keep for yourself.

Re:Object Pointer Problem


Quote
Scott Serven wrote:

> I would like to be able to override certain
> interrupts within my turbo vision apps. The problem
> arises when I have something like this.

> AObject = object(TObject)
>   Timer : LongInt;
>   Procedure NewTimer; virtual;
>   Procedure HookTimer; virtual;
>  End;

> Procedure AObject.NewTimer;
> Begin
>   Inc(Timer);
> End;

> Procedure AObject.HookTimer; virtual;
> Begin
>   SetIntVec($1C, @NewTimer);
> End;

> The SetIntVec returns a compiler error. Apparently I can't address a virtual procedure
> using the @. I get an invalid procedure or function error. So, how do I get a pointer
> to a virtual procedure?

Hi, you can't use an object method to process timer interrupts because a object method
calls always have an implicit parameters (Self) which is a pointer to the object.
This parameters is hidden but the procedure NewTimer actually behaves like this :

Procedure AObject.NewTimer (Self : Pointer);

begin
  Inc (Timer);
end;

Whwn a timer interrupt takes place, the object method is called without the 'Self' parameter pushed
onto the stack, so the contents of the Self pointer will be bogus. The reference to the variable
Timer will inevitably result in a system crash.
To my knowledge, there is only one way to handle this situation and that is like this :

Var
  SomeObject : ^AObject;

{$F+}
Procedure NewTimer; interrupt;

begin
  Inc (SomeObject^.Timer);
end;
{$F-}

This solution is a little too simple as the timer procedure has to save all the registers
and clear the interrupt flag when it exits, but I can't exactly remember how to do it.
Mail me if you want a complete solution and I'll send it to you.

Ciao,
Menno,
s795...@dutiwy.twi.tudelft.nl

Other Threads