Passing a Pointer to a Member Function to the Win32 API

Last reviewed: November 2, 1995
Article ID: Q102352
The information in this article applies to:
  • Microsoft Win32 Application Programming Interface (API) included with:

        - Microsoft Windows NT versions 3.1, 3.5, and 3.51
        - Microsoft Windows 95 version 4.0
    

SUMMARY

Many of the Win32 application programming interfaces (APIs) call for a callback routine. One example is the lpStartAddr argument of CreateThread():

   HANDLE CreateThread(lpsa, cbStack, lpStartAddr, lpvThreadParm,
      fdwCreate, lpIDThread)

   LPSECURITY_ATTRIBUTES lpsa;    /* Address of thread security attrs */
   DWORD cbStack;                    /* Initial thread stack size*/
   LPTHREAD_START_ROUTINE lpStartAddr; /* Address of thread function */
   LPVOID lpvThreadParm;       /* Argument for new thread*/
   DWORD fdwCreate;               /* Creation flags*/
   LPDWORD lpIDThread;               /* Address of returned thread ID */

When attempting to use a member function as the thread function, the following error is generated:

   error C2643: illegal cast from pointer to member

The problem is that the function expects a C-style callback, not a pointer to a member function. A major difference is that member functions are called with a hidden argument called the "this" pointer. In addition, the format of the pointer isn't simply the address of the first machine instruction, as a C pointer is. This is particularly true for virtual functions.

If you want to use a member function as a callback, you can use a static member function. Static member functions do not receive the "this" pointer and their addresses correspond to an instruction to execute.

Static member functions can only access static data, and therefore to access nonstatic class members, the function needs an object or a pointer to an object. One solution is to pass in the "this" pointer as an argument to the member function.

MORE INFORMATION

This situation occurs with callback functions of other types as well, such as:

   DLGPROC                  GRAYSTRINGPROC
   EDITWORDBREAKPROC        LINEDDAPROC
   ENHMFENUMPROC            MFENUMPROC
   ENUMRESLANGPROC          PROPENUMPROC
   ENUMRESNAMEPROC          PROPENUMPROCEX
   ENUMRESTYPEPROC          TIMERPROC
   FONTENUMPROC             WNDENUMPROC
   GOBJENUMPROC

For more information on C++ callbacks, please see the May 1993 issue of the "Windows Tech Journal."

The following sample demonstrates how to use a static member function as a thread function, and pass in the "this" pointer as an argument.

Sample Code

#include <windows.h>

class A { public:
   int x;
   int y;

   A() { x = 0; y = 0; }

   static StartRoutine( A * );   // Compiles clean, includes "this" pointer
};

void main( )
{
   A a;

   DWORD dwThreadID;

   CreateThread( NULL,
      0,
      (LPTHREAD_START_ROUTINE)(a.StartRoutine),
      &a,                        // Pass "this" pointer to static member fn
      0,
      &dwThreadID
   );
}


Additional reference words: 3.10 3.50 4.00 95
KBCategory: kbprg
KBSubcategory: BseMisc


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: November 2, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.