How to declare a class member as a callback? 
Author Message
 How to declare a class member as a callback?

I have an executable and a DLL. I wish to call a function in the DLL
(call it TestCallback() ) which will accept as a parameter the address
of a callback function [ CallMe() ], which resides in the executable. I
have no problems doing this if all the functions involved are
free-standing, that is, not members of classes, viz:
/*********************************************THIS
WORKS****************************************************/
EXE.H:
void CALLBACK CallMe(void);

EXE.CPP:
void CALLBACK CallMe(void)
{
    ...stuff ...

Quote:
}

[....executing code inside MyClass member function...]
TestCallback(CallMe); //call DLL w/ address of callback
...

DLL.H:
int __declspec(__dllexport) TestCallback(void CALLBACK CbFunc(void));

DLL.CPP:
int TestCallback(void CALLBACK CbFunc(void))
{
    CbFunc(); //works, calls "CallMe() " in the EXE

Quote:
}

/************************************THIS IS
HOSED*************************************************************/

Dandy, so far. Now I want to make the callback a member of my class
MyClass, like so:

EXE2.H:
class MyClass
{
    public:
        void CALLBACK CallMe(void);

Quote:
};

EXE2.CPP:

void CALLBACK MyClass::CallMe(void)
{
    ...stuff...

Quote:
}

[..inside a MyClass member function, we call ...]
TestCallBack(CallMe);         //should work, right?

..but the compiler chokes and spews:
error C2664: 'TestCallback' : cannot convert parameter 1 from 'void
(void)' to 'void (__cdecl *)(void)'

I have tried all manner of combinations of CALLBACK (which is defined as
__stdcall in a header), __cdecl, __stdcall, etc., etc., but oddly I
always get the identical message ... weird. In other words, changing
declarations in both the DLL and the EXE's source does not help.

Can anyone point me to a reference, or better yet, an example?

Everything is in the same address space - no COM no DDE no nuttin.

Thanks a lot,

efowler {at} dcn.com OR
sockeye {at} rmii.com



Sun, 10 Jun 2001 03:00:00 GMT  
 How to declare a class member as a callback?
You can't.  If CallMe(void) is a member function, the only way to call it from outside its class is:

   pObject->CallMe();

and not:

   CallMe();

Right?  Callback functions have to be static or global.  Then you can make it __cdecl, __stdcall, etc., etc.



Mon, 11 Jun 2001 03:00:00 GMT  
 How to declare a class member as a callback?
There are some options available.

One method is to define a static callback function, embed the 'this'
pointer within the parameters to the function, such that the static
callback function call dispatch to the right member function with
the right 'this' pointer. For example, you can set the WND GWL_USER
field to be 'this' pointer. This method make subclassing very hard.

Another way is using some assembly code within the class instance,
which sets the 'this' pointer of the object and dispatches to the right
member function with the right 'this' pointer. Very efficient, but not
very portable. ATL is close to this, it supports several CPUs.

The MFC way is to use hook, static function and HWND to CWindow pointer
map to solve the similar problem. I consider MFC's CWindow implementation
to be ugly and slow.

The best way is certainly push Microsoft to add C++ support into their
API. Microsoft will certainly uses the COM interface to achieve that.

Feng Y
=========


Quote:

>I have an executable and a DLL. I wish to call a function in the DLL
>(call it TestCallback() ) which will accept as a parameter the address
>of a callback function [ CallMe() ], which resides in the executable. I
>have no problems doing this if all the functions involved are
>free-standing, that is, not members of classes, viz:
>/*********************************************THIS
>WORKS****************************************************/
>EXE.H:
>void CALLBACK CallMe(void);

>EXE.CPP:
>void CALLBACK CallMe(void)
>{
>    ...stuff ...
>}

>[....executing code inside MyClass member function...]
>TestCallback(CallMe); //call DLL w/ address of callback
>...

>DLL.H:
>int __declspec(__dllexport) TestCallback(void CALLBACK CbFunc(void));

>DLL.CPP:
>int TestCallback(void CALLBACK CbFunc(void))
>{
>    CbFunc(); //works, calls "CallMe() " in the EXE
>}

>/************************************THIS IS
>HOSED*************************************************************/

>Dandy, so far. Now I want to make the callback a member of my class
>MyClass, like so:

>EXE2.H:
>class MyClass
>{
>    public:
>        void CALLBACK CallMe(void);
>};

>EXE2.CPP:

>void CALLBACK MyClass::CallMe(void)
>{
>    ...stuff...
>}

>[..inside a MyClass member function, we call ...]
>TestCallBack(CallMe);         //should work, right?

>..but the compiler chokes and spews:
>error C2664: 'TestCallback' : cannot convert parameter 1 from 'void
>(void)' to 'void (__cdecl *)(void)'

>I have tried all manner of combinations of CALLBACK (which is defined as
>__stdcall in a header), __cdecl, __stdcall, etc., etc., but oddly I
>always get the identical message ... weird. In other words, changing
>declarations in both the DLL and the EXE's source does not help.

>Can anyone point me to a reference, or better yet, an example?

>Everything is in the same address space - no COM no DDE no nuttin.

>Thanks a lot,

>efowler {at} dcn.com OR
>sockeye {at} rmii.com

--
-------------------------------------------------------
Pacifier Online Data Service Dialup SLIP/PPP User
To register: (360) 693-0325 or telnet pods.pacifier.com
-------------------------------------------------------


Mon, 11 Jun 2001 03:00:00 GMT  
 How to declare a class member as a callback?
You can't use a C++ member function as a callback unless it is declared as
static.

Why? Because member functions take an invisible additional parameter (this)
that can't be created on the stack by the calling code (the caller isn't
even aware that it is calling a C++ member function). Moreover, member
functions are decorated, which adds another problem to the list.

The problem when declaring a static member function is that this function
will not have access to the class instance attributes (because it doesn't
have any "this" pointer). So, whatever your choice (static member function
or global function - which is approximatively the same), you'll have to
imagine a way to make the global function communicate with your class
instance.

Patrick Philippot (MainSoft sarl)

http://ourworld.compuserve.com/homepages/mainsoft
tel/fax: +33 (0)1 69 40 94 85



Mon, 11 Jun 2001 03:00:00 GMT  
 How to declare a class member as a callback?

Quote:
>I have an executable and a DLL. I wish to call a function in the DLL
>(call it TestCallback() ) which will accept as a parameter the address
>of a callback function [ CallMe() ], which resides in the executable. I
>have no problems doing this if all the functions involved are
>free-standing, that is, not members of classes, viz:

As others have posted, a callback needs to be a static member, and you
need to have some mechanism to get the instance data (this pointer)
for the class once inside the callback.

Since you aren't so familiar with how C++ handles instance data, I
assume you don't have so much experience yet with C++.  I wonder if
you don't need a call back for your design at all, but because that is
the C way, you are tring to do it that way in C++.  Usually the only
time you need a callback member in a class is when a Windows API
routine requires a callback.

You might be able to do your design with a base class in the dll,
export that class, and have a derived class in the application.  With
this design, the compiler will take care of all the details of passing
instance data.  An example follows.  Try stepping through it in the
de{*filter*} to see which functions get called.

Best regards,
G. Levand

//--- dll.h ---
#if defined(BUILD_DLL)
# define DLL_EXPORT __declspec(dllexport)
# pragma message("DLL - Win32 dll(export) build.")
#else
# define DLL_EXPORT __declspec(dllimport)
# pragma message("DLL - Win32 app(import) build.")
#endif // BUILD_DLL.

class DLL_EXPORT CDllBase
{
        void fn1();
        virtual void fn2();

Quote:
};

//--- dll.cpp ---
#define BUILD_DLL
#include dll.h
void CDllBase::fn1()
{
   fn2(); // virtual - calls into app since app has an fn2().

Quote:
}      

//--- app.cpp ---
#include dll.h
class CApp public CDllBase
{
        void fn2();
        void fn3();
Quote:
};

void CApp::fn2()
{
Quote:
}

void _cdecl main()
{
   CApp x;
   x.fn1();     // calls into dll.
   x.fn2();     // calls CApp's fn2().
Quote:
}



Tue, 12 Jun 2001 03:00:00 GMT  
 How to declare a class member as a callback?
You cannot call a class member as a callback because it expects the
first parameter to be 'this', a pointer to the class instance. Since
you have already indicated that the callback takes no parameters, you
can declare it as 'static' in the class:
        static void CALLBACK CallMe(void);

this will work, because it is the same as your example that works.
However, this does not give you access to a class instance. If you
need that, the best workaround I've found is to declare it as
        static void CALLBACK CallMe(MyClass * param);

and then pass back a class instance parameter from the DLL. If you
don't need a class instance, the first example will work.
                                joe



Quote:
>I have an executable and a DLL. I wish to call a function in the DLL
>(call it TestCallback() ) which will accept as a parameter the address
>of a callback function [ CallMe() ], which resides in the executable. I
>have no problems doing this if all the functions involved are
>free-standing, that is, not members of classes, viz:
>/*********************************************THIS
>WORKS****************************************************/
>EXE.H:
>void CALLBACK CallMe(void);

>EXE.CPP:
>void CALLBACK CallMe(void)
>{
>    ...stuff ...
>}

>[....executing code inside MyClass member function...]
>TestCallback(CallMe); //call DLL w/ address of callback
>...

>DLL.H:
>int __declspec(__dllexport) TestCallback(void CALLBACK CbFunc(void));

>DLL.CPP:
>int TestCallback(void CALLBACK CbFunc(void))
>{
>    CbFunc(); //works, calls "CallMe() " in the EXE
>}

>/************************************THIS IS
>HOSED*************************************************************/

>Dandy, so far. Now I want to make the callback a member of my class
>MyClass, like so:

>EXE2.H:
>class MyClass
>{
>    public:
>        void CALLBACK CallMe(void);
>};

>EXE2.CPP:

>void CALLBACK MyClass::CallMe(void)
>{
>    ...stuff...
>}

>[..inside a MyClass member function, we call ...]
>TestCallBack(CallMe);         //should work, right?

>..but the compiler chokes and spews:
>error C2664: 'TestCallback' : cannot convert parameter 1 from 'void
>(void)' to 'void (__cdecl *)(void)'

>I have tried all manner of combinations of CALLBACK (which is defined as
>__stdcall in a header), __cdecl, __stdcall, etc., etc., but oddly I
>always get the identical message ... weird. In other words, changing
>declarations in both the DLL and the EXE's source does not help.

>Can anyone point me to a reference, or better yet, an example?

>Everything is in the same address space - no COM no DDE no nuttin.

>Thanks a lot,

>efowler {at} dcn.com OR
>sockeye {at} rmii.com

Joseph M. Newcomer

http://www3.pgh.net/~newcomer


Thu, 14 Jun 2001 03:00:00 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. Declaring static document class with callbacks

2. Declaring static document class with callbacks

3. How to declare a pointer to a member function (in a different class)

4. Declaring Static Members of a class

5. Declaring class member variables that require a constructor argument

6. How can I declare and use const member variable in a class

7. Declaring a class member as stdcall

8. Declaring a class member as stdcall

9. Declaring STL vector/list as a member of a class with VC6

10. Declaring Arrays members of a class.

11. Accessing class member functions from Global Callback

12. Syntax problem: WSAAsyncSelect doesn't like callbacks that are members of a class

 

 
Powered by phpBB® Forum Software