Thread: Callback function as class method

  1. #16
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Read the beginning of this thread. The OP was trying to solve exactly this problem.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  2. #17
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well, anyway, it should work if the wrapper is static.
    Not the prettiest solution, but it's something you have to accept due to C api.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #18
    Registered User
    Join Date
    May 2008
    Posts
    13
    Thanks for pointing that out on the wrapper function. I will try again, but yesterday evening I thought I tried that, but didn't work. Just curious, since I'm writing this code in visual embedded C++ so that doesn't really limit me right regarding on this issue?

  4. #19
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> that doesn't really limit me right regarding on this issue?
    No.

    gg

  5. #20
    Registered User
    Join Date
    May 2008
    Posts
    13
    It seems I'm unable to accomplish callling class member within a static CALLBACK function, can you please give me suggestion.

    Code:
    class MyTest
    {
    public:
    
    	//Default constructor.
    	MyTest();
    
    	//Destructor.
    	~MyTest(){};
    
    	void SetFileName(LPCWSTR fName);
    	LPCWSTR GetFileName();
    	void SetGlobalString(TCHAR tempStr[]);
    
    
    	//Play audio and sound:
    	void Manual_Test(HINSTANCE hInstance);
    	static BOOL CALLBACK playTone(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam);
    
    private:
    
    	WriteFile logResult; //my another class
    	LPCWSTR manualTempFileName;
    };
    Code:
    //myTest.cpp
    
    MyTest::MyTest():manualTempFileName(NULL), logResult(NULL)
    {
    }
    
    void MyTest::Manual_Test(HINSTANCE hInstance)
    {
    
    	DialogBox(hInstance, MAKEINTRESOURCE(IDD_AUDIOPLAYTONE), 
    		NULL, MyTest::playTone);
    
    }
    
    
    
    BOOL CALLBACK MyTest::playTone(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
    
    	switch(Msg)
    	{
    
    	case WM_COMMAND:
    
    		switch(wParam)
    		{
    
    		case IDAUDIOPLAYTONE: 
    			{
    
    				DWORD pitchValue = IDC_INPUTPTCH;
    				DWORD durationValue = IDC_INPUTDURATION;
    				DWORD volumeValue = IDC_INPUTVOLUME;
    
                                                                    //This function takes in four parameters.
    				PlayAudio(pitchValue, durationValue, volumeValue);
    
    				MyTest* temp ;
    				temp->logResult.OpenFile(globalFileName);	
    				temp->logResult.WriteAudio(pitchValue, TEXT("pitch"));
    				temp->logResult.WriteAudio(durationValue, TEXT("duration"));
    				temp->logResult.WriteAudio(volumeValue, TEXT("volume"));
    				temp->logResult.CloseFile();
    
    			}
    			return TRUE;
    			break;
    
    		case IDEXIT:
    			EndDialog(hWndDlg, 0);
    			return TRUE;
    			break;
    
    		}
    		break;
    
    	case WM_CLOSE:
    		DestroyWindow(hWndDlg);
    		return TRUE;
    		break;
    		
    	}
    
    	return FALSE;
    }
    I try to call and open the file to write data into the log file, but the message says it's an access voilation, and I have no idea to fix. Although I tried to declare global pointer that schifers did, but still gives the same error.
    Last edited by lakewa; 05-19-2008 at 11:31 AM.

  6. #21
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    ManualTest* temp ;
    This variable is never set to point to anything...

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #22
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    	DialogBox(hInstance, MAKEINTRESOURCE(IDD_AUDIOPLAYTONE), 
    		NULL, &MyTest::playTone);
    Illegal. Class members must have a & to take the address (correction in red).
    Code:
    				ManualTest* temp ;
    				temp->logResult.OpenFile(globalFileName);	
    				temp->logResult.WriteAudio(pitchValue, TEXT("pitch"));
    				temp->logResult.WriteAudio(durationValue, TEXT("duration"));
    				temp->logResult.WriteAudio(volumeValue, TEXT("volume"));
    				temp->logResult.CloseFile();
    Use of unallocated memory.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #23
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    Code:
    	DialogBox(hInstance, MAKEINTRESOURCE(IDD_AUDIOPLAYTONE), 
    		NULL, &MyTest::playTone);
    Illegal. Class members must have a & to take the address (correction in red).
    I'm 99.9% sure the original code is fine. I don't see a reason for why it would be different just because the function is a class. A function-name that hasn't got () on the end means "The address of this function".

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #24
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    A function of a class must use & to take the address. The exception is free functions.
    I believe it's a requirement set forth by C++, but an exception was made for free functions due to backwards compability.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #25
    Registered User
    Join Date
    May 2008
    Posts
    13
    Quote Originally Posted by matsp View Post
    Code:
    ManualTest* temp ;
    This variable is never set to point to anything...

    --
    Mats

    That is what I thought because using pointer without initialization, but I couldn't think of what to assign to.

  11. #26
    Registered User
    Join Date
    May 2008
    Posts
    13
    Quote Originally Posted by Elysia View Post
    A function of a class must use & to take the address. The exception is free functions.
    I believe it's a requirement set forth by C++, but an exception was made for free functions due to backwards compability.
    I just add & like you suggested, but when I step through the function function to open the log file, it gives the same error messsage. In the open file function, the name of the file is passed in as parameter and it's shown. Do I initialize my WriteFile logResult as well? but I thought I did that in my constructor.

  12. #27
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by lakewa View Post
    That is what I thought because using pointer without initialization, but I couldn't think of what to assign to.
    If you want it to point to the original class, then the simplest thing to do is to create a global variable that points to the current class. This is not good design for a multithreaded environment, but seeing as Windows API is not exactly tolerant of multithreading in itself, it's probably a non-issue.

    So in code:
    Code:
    MyTest *gPtrMyTest;
    
    void MyTest::Manual_Test(HINSTANCE hInstance)
    {
            gPtrMyTest = this;
    	DialogBox(hInstance, MAKEINTRESOURCE(IDD_AUDIOPLAYTONE), 
    		NULL, MyTest::playTone);
    
    }
    
    BOOL CALLBACK MyTest::playTone(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
    ...
        MyTest *temp = gPtrMyTest;
    ...
    Or you could even use gPtrMyTest directly.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #28
    Registered User
    Join Date
    May 2008
    Posts
    13
    Quote Originally Posted by matsp View Post
    If you want it to point to the original class, then the simplest thing to do is to create a global variable that points to the current class. This is not good design for a multithreaded environment, but seeing as Windows API is not exactly tolerant of multithreading in itself, it's probably a non-issue.

    So in code:
    Code:
    MyTest *gPtrMyTest;
    
    void MyTest::Manual_Test(HINSTANCE hInstance)
    {
            gPtrMyTest = this;
    	DialogBox(hInstance, MAKEINTRESOURCE(IDD_AUDIOPLAYTONE), 
    		NULL, MyTest::playTone);
    
    }
    
    BOOL CALLBACK MyTest::playTone(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
    ...
        MyTest *temp = gPtrMyTest;
    ...
    Or you could even use gPtrMyTest directly.

    --
    Mats

    I'm not worrying about threading right now because I'm not using any also it's out of my scope right now about threading. But I will try your suggestion, and hope it will work. Thanks.

  14. #29
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    A function of a class must use & to take the address. The exception is free functions.
    I believe it's a requirement set forth by C++, but an exception was made for free functions due to backwards compability.
    Code:
    D:\temp>g++ -Wall -Wextra -ansi -pedantic fun.cpp
    
    D:\temp>cat fun.cpp
    #include <iostream>
    
    class foo
    {
    public:
      static void bar(int x) { std::cout << x << std::endl; }
    };
    
    
    
    void fun(void (*f)(int x))
    {
      f(7);
    }
    
    int main()
    {
      fun(foo::bar);
      return 0;
    }
    Works just fine like that, no need for &.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #30
    Registered User
    Join Date
    May 2008
    Posts
    13
    matsp, thanks the error is gone. But may I know why it's necessary to assign it to the object itself.

    gPtrMyTest = this;
    MyTest *temp = gPtrMyTest;

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  2. My Window Class
    By Epo in forum Game Programming
    Replies: 2
    Last Post: 07-10-2005, 02:33 PM
  3. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 10:18 AM
  4. structure vs class
    By sana in forum C++ Programming
    Replies: 13
    Last Post: 12-02-2002, 07:18 AM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM