Read the beginning of this thread. The OP was trying to solve exactly this problem.
Printable View
Read the beginning of this thread. The OP was trying to solve exactly this problem.
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.
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?
>> that doesn't really limit me right regarding on this issue?
No.
gg
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;
};
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.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;
}
This variable is never set to point to anything...Code:ManualTest* temp ;
--
Mats
Illegal. Class members must have a & to take the address (correction in red).Code:DialogBox(hInstance, MAKEINTRESOURCE(IDD_AUDIOPLAYTONE),
NULL, &MyTest::playTone);
Use of unallocated memory.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();
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.
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:
Or you could even use gPtrMyTest directly.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;
...
--
Mats
Works just fine like that, no need for &.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;
}
--
Mats
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;