Click here to Skip to main content
15,919,423 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
GeneralRe: Newbie GDI question Pin
David Crow12-Apr-04 3:53
David Crow12-Apr-04 3:53 
GeneralFile reading Pin
perozbabu12-Apr-04 2:10
perozbabu12-Apr-04 2:10 
GeneralRe: File reading Pin
David Crow12-Apr-04 3:58
David Crow12-Apr-04 3:58 
GeneralForm Width/Height & Pointer problem Pin
uus9912-Apr-04 2:02
uus9912-Apr-04 2:02 
GeneralCompiler Error Pin
Kash12-Apr-04 1:58
Kash12-Apr-04 1:58 
GeneralRe: Compiler Error Pin
Nitzan Shaked12-Apr-04 2:47
Nitzan Shaked12-Apr-04 2:47 
GeneralRe: Compiler Error Pin
Kash12-Apr-04 3:24
Kash12-Apr-04 3:24 
GeneralRe: Compiler Error Pin
Nitzan Shaked12-Apr-04 7:05
Nitzan Shaked12-Apr-04 7:05 
All options will work for you, since all options will result with DriverFunc() being called on the correct object. The way I usually do it is option (2), actually. It's a small price to pay (1 line of code) for the generic mechanism you gain.

Just in case we're not talking about the same thing when we're saying "option (2)", here's what I mean (in an all-madeup example):

Let's say you have a function (or a method of some class) which needs to call some "callback" function with three parameters: an int, a double, and a char. It's customary anyways to add a "context" or "userdata" argument to such callback functions (even in plain C) so you can use the same function for several callbacks, and each of the callers will pass a different first argument ("userdata") according to what was requested when the cb func was registered.

In our case we replace this "context" / "user data" with a pointer to the actual C++ instance.

We define a type for the cb func: ClassMethodCbFunc -- it gets our int,double,char arguments, plus another parameter which will become the "this".

-------------------------------------------------------------------------------------------
typedef int (*ClassMethodCbFunc)( void* This, int Param1, double Param2, char Param3 );
// (Note: "This" and not "this" !)
-------------------------------------------------------------------------------------------

The function (or some class method) which wants to use this type looks like:

-------------------------------------------------------------------------------------------
void FunctionWhichCallsMethodCb( ClassMerhodCbFunc Func, void* This )
{
...
int Res = Func( This, 1, 2.0, 'c' );
...
}
-------------------------------------------------------------------------------------------

... that is: it calls it's "Func" argument with the "This" parameter it receives, and the values for Param1, Param2 and Param3 can be anything. ("Func" and "This" go together: when one is passed for a func to another, so will the other one. Just like the "CbFunc" and "userdata" in "plain" C).

Now for the class which actually contains the method that will eventually be called:

-------------------------------------------------------------------------------------------
class CMyClass
{
public:
int MemthodBeingCalled( int Param1, double Param2, char Param3 )
{
return Param1 + Param2 + Param3;
}

static int MethodBeingCalled__Wrapper( void* This, int Param1, int Param2, char Param3 )
{
return ((CMyClass*)This)->MethodBeingCalled( Param1, Param2, Param3 );
}
}
-------------------------------------------------------------------------------------------

... Note MethodBeingCalled__Wrapper: it's static, so we can take it's address. (It does NOT receive a hidden "this" argument, since it's static!).

The way to actually use of all of this:

-------------------------------------------------------------------------------------------
CMyClass MyInstance;

FunctionWhichCallsMethodCb( CMyClass::MethodBeingCalled__Wrapper,
&MyInstance );
-------------------------------------------------------------------------------------------


Finally -- regarding the (in)famous "option (3)" :

In a nutshell, you can't take the address of class methods if they're virtual (or you can, but the function whose address you'll be getting will be resolved in linkage, not run-time, so you won't be getting the "latest implementation" -- always the same class name you mention). Also, you need to be aware of calling conventions etc...

The idea I found was this: you can circumnavigate the type checking by using a mechanism designed just (well... sorta) for that: ellipses.

If you write a function such as

void* ToVoidStar( void* Dummy, ... )
{
// Use "va_list" here to get the first argument and return it as a void*
}

And call it like:

void* Addr = ToVoidStar( 0, CMyClass::SomeMethod )

you will get the address of CMyClass::SomeMethod() in "Addr".

You then need to write a function to CALL such the method pointed to by "Addr" -- it's not a simple matter of casting it to a function-pointer type and calling it via the pointer, since in __stdcall "this" is passed in ECX.

So we need some small function, a "thunk", which accepts a "this" pointer, some parameters, and does "mov ecx,[This] ; push PARAMS ; call [Func]" (rough sketch, of course...).

This will only work for __stdcall functions, of course, which are (basically) all methods with a constant number of arguments (not ellipses!).

Maybe I should write an article on this?

-- Calius
GeneralRe: Compiler Error Pin
Kash13-Apr-04 23:05
Kash13-Apr-04 23:05 
GeneralSplitters! Message Box Pin
ZoomBoy2712-Apr-04 1:49
ZoomBoy2712-Apr-04 1:49 
GeneralRe: Splitters! Message Box Pin
ZoomBoy2712-Apr-04 2:00
ZoomBoy2712-Apr-04 2:00 
QuestionHard Drive, BIOS and CPU serial number in VC++ 6.0? Pin
Freddie Code12-Apr-04 1:15
Freddie Code12-Apr-04 1:15 
AnswerRe: Hard Drive, BIOS and CPU serial number in VC++ 6.0? Pin
Milton Karimbekallil12-Apr-04 1:57
Milton Karimbekallil12-Apr-04 1:57 
AnswerRe: Hard Drive, BIOS and CPU serial number in VC++ 6.0? Pin
David Crow12-Apr-04 4:12
David Crow12-Apr-04 4:12 
AnswerRe: Hard Drive, BIOS and CPU serial number in VC++ 6.0? Pin
Darshan Jani12-Apr-04 7:47
Darshan Jani12-Apr-04 7:47 
GeneralTrouble with _variant_t Pin
yanuart12-Apr-04 1:08
yanuart12-Apr-04 1:08 
GeneralRe: Trouble with _variant_t Pin
Milton Karimbekallil12-Apr-04 1:48
Milton Karimbekallil12-Apr-04 1:48 
QuestionAre there somewhere good articles about MTS ? Pin
vgrigor12-Apr-04 0:53
vgrigor12-Apr-04 0:53 
Generalunsigned chars Pin
packetlos12-Apr-04 0:10
packetlos12-Apr-04 0:10 
GeneralRe: unsigned chars Pin
John R. Shaw12-Apr-04 0:37
John R. Shaw12-Apr-04 0:37 
GeneralRe: unsigned chars Pin
packetlos12-Apr-04 1:21
packetlos12-Apr-04 1:21 
GeneralRe: unsigned chars Pin
packetlos12-Apr-04 5:38
packetlos12-Apr-04 5:38 
Generaldouble and float variables Pin
deniz79s12-Apr-04 0:04
deniz79s12-Apr-04 0:04 
GeneralRe: double and float variables Pin
John R. Shaw12-Apr-04 0:46
John R. Shaw12-Apr-04 0:46 
QuestionWhich DLLs do I have to distribute AND which DLLs can I expect to be already installed on a standard XP installation? Pin
Tony Westminster12-Apr-04 0:04
Tony Westminster12-Apr-04 0:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.