BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

TimeSetEvent

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Native API)
View previous topic :: View next topic  
Author Message
David Dean
Guest





PostPosted: Fri Apr 28, 2006 5:03 pm    Post subject: TimeSetEvent Reply with quote



I'm having trouble using the TimeSetEvent API call. The following
source fails to compile:

//-----------------------------------------------------------------------
#include <vcl.h>

#pragma hdrstop

//-----------------------------------------------------------------------
#pragma package(smart_init)

class myClass
{
public:
void send(AnsiString outString, int delay, unsigned short timeout);
void CALLBACK OneShotTimer(UINT wTimerID, UINT msg, DWORD dwUser,
DWORD dw1, DWORD dw2);
};

void myClass::send(AnsiString outString, int delay, unsigned short
timeout)
{
timeSetEvent(timeout, 100, (LPTIMECALLBACK)&OneShotTimer, NULL,
TIME_ONESHOT);
}
//-----------------------------------------------------------------------
void CALLBACK myclass::OneShotTimer(UINT wTimerID, UINT msg,
DWORD dwUser, DWORD dw1, DWORD dw2)
{

}
//-----------------------------------------------------------------------

I know there are pieces missing, but can someone get me on the right
track? I'm sure it is an obvious mistake, but I've looked at it to long.
The error produced by the compiler is:

[C++ Error] Unit1.cpp(22): E2031 Cannot cast from 'void (__stdcall *
(_closure )(unsigned int,unsigned int,unsigned long,unsigned
long,unsigned
long))(unsigned int,unsigned int,unsigned long,unsigned long,unsigned
long)'
to 'void (__stdcall *)(unsigned int,unsigned int,unsigned long,unsigned
long,unsigned long)'

-David

--
-David

Nihil curo de ista tua stulta superstitione.
Back to top
David Dean
Guest





PostPosted: Fri Apr 28, 2006 6:03 pm    Post subject: Re: TimeSetEvent Reply with quote



In article <44524b44$1 (AT) newsgroups (DOT) borland.com>,
"Remy Lebeau \(TeamB\)" <no.spam (AT) no (DOT) spam.com> wrote:

Quote:
For example:

Excellent example. Thank you. I had a feeling that the solution was
something along those lines, but my mind went blank.

--
-David

Nihil curo de ista tua stulta superstitione.
Back to top
David Dean
Guest





PostPosted: Fri Apr 28, 2006 6:03 pm    Post subject: Re: TimeSetEvent Reply with quote



In article <32i4521k20p3ha1bq744jvbfteei2kr01q (AT) 4ax (DOT) com>,
Bob Gonder <notbg (AT) notmindspring (DOT) invalid> wrote:

Quote:
Asked many times on this very group.
You might Google for "nativeapi _closure"

Thanks Bob. It should have been obvious to google those terms, but I
must have been looking at it too long to think straight. Remy's example
was exactly the jog I needed for my memory.

--
-David

Nihil curo de ista tua stulta superstitione.
Back to top
Bob Gonder
Guest





PostPosted: Fri Apr 28, 2006 6:03 pm    Post subject: Re: TimeSetEvent Reply with quote

David Dean wrote:

Quote:
class myClass
{
void CALLBACK OneShotTimer(UINT wTimerID, UINT msg, DWORD dwUser,
};
timeSetEvent(timeout, 100, (LPTIMECALLBACK)&OneShotTimer, NULL,
TIME_ONESHOT);

[C++ Error] Unit1.cpp(22): E2031 Cannot cast from 'void (__stdcall *
(_closure )(unsigned int,unsigned int,unsigned long,unsigned

Asked many times on this very group.
You might Google for "nativeapi _closure"

Bottom line is callbacks must be static or else non-members.
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Fri Apr 28, 2006 6:03 pm    Post subject: Re: TimeSetEvent Reply with quote

"David Dean" <ozchzhq02 (AT) sneakemail (DOT) com> wrote in message
news:ozchzhq02-9725F7.12284128042006 (AT) frylock (DOT) local...

Quote:
The error produced by the compiler is:

You are trying to use a non-static class method as the callback. You cannot
do that (not directly, anyway). Such a method requires a 'this' pointer be
passed to it when called. TimeSetEvent() does not know how to do that. It
expects a standalone function as the callback. In order to use a class
method, you must declare it as 'static'. The only downside is that the
callback will no longer be able to access non-static members of the class,
since no 'this' pointer is available. Fortunately, TimeSetEvent() allows
you to specify your own 32-bit value in the dwUser parameter, and that value
will be passed to the callback. So you can pass the class's 'this' pointer
in that parameter. For example:

class myClass
{
private:
int value; // <-- for deomstration only
static void CALLBACK OneShotTimer(UINT wTimerID, UINT msg, DWORD
dwUser, DWORD dw1, DWORD dw2);
public:
void send(const AnsiString &outString, int delay, unsigned short
timeout);
};

void myClass::send(const AnsiString &outString, int delay, unsigned
short timeout)
{
//...
value = 0;
timeSetEvent(timeout, 100, &OneShotTimer,
reinterpret_cast<DWORD>(this), TIME_ONESHOT);
}

void CALLBACK myClass::OneShotTimer(UINT wTimerID, UINT msg, DWORD
dwUser, DWORD dw1, DWORD dw2)
{
myClass *pThis = reinterpret_cast<myClass*>(dwUser);

// use pThis as needed ...
pThis->value = 1;
}


Gambit
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Fri Apr 28, 2006 8:03 pm    Post subject: Re: TimeSetEvent Reply with quote

"Bob Gonder" <notbg (AT) notmindspring (DOT) invalid> wrote in message
news:32i4521k20p3ha1bq744jvbfteei2kr01q (AT) 4ax (DOT) com...

Quote:
Bottom line is callbacks must be static or else non-members.

There is a third option, though not very straight forward - use a proxy.
That is what the VCL does to allow non-static class methods to be used as
Win32 API window procedure callbacks. Basically, for each desired method
for each class instance, you allocate a block of executable memory that
contains a stub function along with the class instance's 'this' pointer and
desired method pointer. Then you can pass the memory block whereever a
non-member callback is expected. When the API calls the callback, the stub
function is executed automatically, which then decodes the parameters from
the call stack and reformats the call stack to place the 'this' pointer onto
the stack, and then jumps into the class method. As far as the class
method's inner code is concerned, it will act exactly as if it had been
called directly by the API without a proxy. It is a very effective
technique, albeit not a trivial one to implement since you have to use
low-level assembly code for the stub function. If you have the VCL source
code installed, you can look at the code for the MakeObjectInstance()
function for an example.

Gambit
Back to top
Bruce Salzman
Guest





PostPosted: Fri Apr 28, 2006 8:03 pm    Post subject: Re: TimeSetEvent Reply with quote

"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote in message
news:445265cc$1 (AT) newsgroups (DOT) borland.com...
Quote:


"There is a third option, though not very straight forward - use a
proxy.
<snip>
....not a trivial one to implement since you have to use low-level
assembly code for the stub function."

see "Kludge"

;^)
--
Bruce
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Fri Apr 28, 2006 11:03 pm    Post subject: Re: TimeSetEvent Reply with quote

" Bruce Salzman" <bruce (AT) nospam (DOT) org> wrote in message
news:44526fbb (AT) newsgroups (DOT) borland.com...

Quote:
see "Kludge"

Not a kluge. It is a very powerful alternative when a callback does not
allow user-defined values and you don't want to use global pointers.


Gambit
Back to top
Bruce Salzman
Guest





PostPosted: Fri Apr 28, 2006 11:03 pm    Post subject: Re: TimeSetEvent Reply with quote

"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote in message
news:44528e06 (AT) newsgroups (DOT) borland.com...
Quote:

" Bruce Salzman" <bruce (AT) nospam (DOT) org> wrote in message
news:44526fbb (AT) newsgroups (DOT) borland.com...

see "Kludge"

Not a kluge. It is a very powerful alternative when a callback does
not
allow user-defined values and you don't want to use global pointers.



One man's kludge is another man's powerful alternative, I guess. It's
one thing for a compiler/library vendor to do this kind of thing, with
(presumably) full knowlege of the pitfalls. It's quite another to put
it in your own application. I would hate to be the next (or next,
or...) programmer hired to maintain something like this, regardless of
how elegent it is in theory.

Just my two cents.

--
Bruce
Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Native API) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.