am trying to make a worker thread using MFC so here is the codes:
struct ThreadParam
{
HWND mDlg; // Note: A handle.
};
UINT TestMFCThread::Test( LPVOID pParam ){
//do work!
}
void TestMFCThread::OnBnClickedButton2()
{
ThreadParam* param = new ThreadParam;
param->mDlg = m_hWnd;
AfxBeginThread(Test, param);
}
but it gives me this error :
1 IntelliSense: no instance of overloaded function "AfxBeginThread" matches the argument list
argument types are: (UINT (LPVOID pParam), ThreadParam *)
idk whats wrong it's supposed to be right!
From the documentation for AfxBeginThread() you need to cast the second argument to LPVOID:
AfxBeginThread(Test, (LPVOID) param);
and set calling convention of Test to __cdecl:
UINT __cdecl Test( LPVOID lParam)
just declare your member function as static , it will solve the issue
Related
I am trying to use the following function of my library in a thread:
typedef void (*TIPO_FUNCION_APARCAR_COMMIT) (HCoche hc);
typedef void (*TIPO_FUNCION_PERMISO_AVANCE) (HCoche hc);
typedef void (*TIPO_FUNCION_PERMISO_AVANCE_COMMIT)(HCoche hc);
int PARKING2_aparcar(HCoche,void *datos,TIPO_FUNCION_APARCAR_COMMIT,
TIPO_FUNCION_PERMISO_AVANCE,
TIPO_FUNCION_PERMISO_AVANCE_COMMIT);
But I can't figure out how I can call it, because in CreateThread() the input parameter is LPVOID and I don't see how I can use it.
I tried this syntax, but it doesn't work:
CreateThread(0, 0, fPARKING2_apagar, {&hc,(LPTHREAD_START_ROUTINE)fPARKING2_getDatos(hc), &commit, &goForward, &goForwardCommit}, NULL, NULL, &threadId);
I also tried to use std::thread, but it seems that I don't have C++11 so I can't use it.
The fPARKING2_apagar() function you are trying to pass to CreateThread() does not satisfy the signature that CreateThread() is expecting. The signature of your thread function MUST match that of ThreadProc():
DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter);
Also, you are trying to pass an anonymous struct to the lpParameter param of CreateThread(). That will not work, either.
You need to write a wrapper function that you can pass to CreateThread(), and then that wrapper can call the library function. Use the lpParameter param of CreateThread() to pass user-defined data to the thread function, which can then pass it on to the library function as needed.
Try something more like this:
struct PARKING2_aparcar_params
{
HCoche hc;
void *datos;
TIPO_FUNCION_APARCAR_COMMIT aparcarCommit;
TIPO_FUNCION_PERMISO_AVANCE permisoAvance;
TIPO_FUNCION_PERMISO_AVANCE_COMMIT permisoAvanceCommit;
};
DWORD WINAPI PARKING2_aparcar_wrapper(LPVOID lpParameter)
{
PARKING2_aparcar_params *params = static_cast<PARKING2_aparcar_params*>(lpParameter);
fPARKING2_aparcar(params->hc, params->datos, params->aparcarCommit, params->permisoAvance, params->permisoAvanceCommit);
delete params;
return 0;
}
...
PARKING2_aparcar_params *params = new PARKING2_aparcar_params;
params->hc = hc;
params->datos = fPARKING2_getDatos(hc);
params->aparcarCommit = &commit;
params->permisoAvance = &goForward;
params->permisoAvanceCommit = &goForwardCommit;
hThread = CreateThread(NULL, 0, &PARKING2_aparcar_wrapper, params, 0, &threadId);
if (!hThread)
delete params;
Below there is a part of my code:
class MyClass
{
...
HANDLE m_ListenThr;
DWORD WINAPI ListenThread (LPVOID WorkContext);
bool CreateListenThreads();
}
bool MyClass::CreateListenThreads()
{
...
m_ListenThr = CreateThread(NULL, 0, MyClass::ListenThread,(void*)this, 0,&dwThreadId);
}
DWORD WINAPI MyClass::ListenThread (LPVOID WorkThreadContext)
{
MyClass pThis = reinterpret_cast<MyClass*>(WorkThreadContext);
...
}
After compiling i get this error:
error C3867: 'MyClass::ListenThread': function call missing argument
list; use '&MyClass::ListenThread' to create a pointer to member
what i do wrong?
You have to define the thread function DWORD WINAPI ListenThread (LPVOID WorkContext); as a static function of the class:
class MyClass
{
public:
static DWORD WINAPI ListenThread (LPVOID WorkContext);
}
It is not possible to call a member function without an instance of an object. In your case this is only a parameter that will be passed as WorkContext in your now static function ListenThread.
As another solution, you could also consider using C++11 std::bind so as to create a function object from that you would pass to CreateThread.
That would go something like this - sorry I have not windows so as to check if this compiles - but it gives you the idea:
bool MyClass::CreateListenThreads()
{
using std::placeholders;
std::function <void (void*)> threadFunction = std::bind(&MyClass::ListenThread, *this, _1);
m_ListenThr = CreateThread(NULL, 0, threadFunction,(void*)this, 0,&dwThreadId);
}
but that would sort of use the reference to this twice: as the instance of the class to call the function on, and as a parameter LPVOID WorkContext. Maybe it's awkward in this present case.
I have defined a function
HRESULT AMEPreviewHandler:: CreateHtmlPreview()
{
ULONG CbRead;
const int Size= 115000;
char Buffer[Size+1];
HRESULT hr = m_pStream->Read(Buffer, Size, &CbRead );
//this m_pStream is not accessible here even it is declared globally. the program is asking me to
// declare it static because this CreateHtmlPreview() function called
//inside the Static function (i mean here :-static CreateDialog\WM_Command\CreateHtmlPreview();)
//but if i declare it static the two problems arised are
//(1.) It is not able to access the value of the m_pStream which is defined globally.
//(2.)If i declare it static globally then there are so many other function which are using this
// value of m_pStream are not able to access it because they are non static.
}
It is declared static somewhere in my program like this:
static HRESULT CreateHtmlPreview(); //i have declared it static because i am calling this function from DialogProc function.If i dont create it static here it dont work
//The function CreateHtmlPreview() is called inside the DialogProc function like this-
BOOL CALLBACK AMEPreviewHandler::DialogProc(HWND m_hwndPreview, UINT Umsg, WPARAM wParam, LPARAM lParam)
{......
case WM_COMMAND:
{
int ctl = LOWORD(wParam);
int event = HIWORD(wParam);
if (ctl == IDC_PREVIOUS && event == BN_CLICKED )
{
CreateHtmlPreview(); //here i am calling the function
return 0;
}
}
}
So what can be done to make the value of non static m_pStream accessible in the static CreateHtmlPreview() function definition ?
In static class functions you can access to only static class members.
What if you make CreateHtmlPreview() a free function?
What if you make it just create an html preview (instead of also reading from a stream)?
void CreateHtmlPreview(const char * buffer, int size)
{
//...
}
Then read the data from the proc, and call it in DialogProc
//...
m_pStream->Read(Buffer, Size, &CbRead );
CreateHtmlPreview(Buffer, Size);
You will probably need to make the function return the preview to be any use though.
You do say you need to make it
static because i am calling this function from DialogProc function
however, the DialogProc is not static (in the code you have posted), so I don't see what the problem would be.
Can't you just pass the m_pStream var as a function argument?
Instead of defining the function this way
HRESULT AMEPreviewHandler:: CreateHtmlPreview()
{
ULONG CbRead;
const int Size= 115000;
char Buffer[Size+1];
HRESULT hr = m_pStream->Read(Buffer, Size, &CbRead );
}
You can do it like this (you should define the stream type!)
HRESULT AMEPreviewHandler:: CreateHtmlPreview(stream)
{
ULONG CbRead;
const int Size= 115000;
char Buffer[Size+1];
HRESULT hr = stream->Read(Buffer, Size, &CbRead );
}
And call it like this
CreateHtmlPreview(m_pStream);
DoctorLove i have solved this problem actually the code by idea of accesing the non static varible using this parameter- the problem was i had not initialized the instance in WM_INITDIALOG now i donze like this-
case WM_INITDIALOG:
{
instance = (AMEPreviewHandler*)lParam;
instance->m_pStream;
return0;
}
and it works fine.
I am playing with lambda in Visual C++ 11.
void CWin32Service::RunService (__in DWORD dwArgc, __in LPTSTR *lpszArgv)
{
auto SvcMainptr = [this](__in DWORD dwArgc, __in LPTSTR *lpszArgv) -> void {ServiceMain( dwArgc, lpszArgv );} ;
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ m_ServiceName, (LPSERVICE_MAIN_FUNCTION)SvcMainptr }, <<== Error HERE
{ NULL, NULL }
};
....
}
The error message I get is:
'type cast' : cannot convert from 'CWin32Service::RunService::<lambda_22F3FB7B8C044A64>' to 'LPSERVICE_MAIN_FUNCTIONW'
That is a Win32 API that expects to take a real function pointer with an exact signature. You can't pass a lambda or other type of function object to it.
You should be passing ServiceMain in the service dispatch table.
invalid conversion from 'DWORD (*)(void*)' to 'DWORD (*)(void*)' .
cake==lie
1==0
I have no idea what this means ... I get it in this code
HANDLE CPlugin::CreateWinampThread() ||
{ __VVVVVVVV__
hWinampThreadHandle = (HANDLE)CreateThread(NULL, 0, StartWinampThread, (void*)this, 0, &dwWinampThreadID);
if (!hWinampThreadHandle)
return 0;
CloseHandle(hWinampThreadHandle);
return hWinampThreadHandle;
}
.
DWORD WINAPI CPlugin::StartWinampThread(void* lpParam)[...]
StartWinampThread must be static if it is member function.
See here: in-c-is-it-safe-portable-to-use-static-member-function-pointer-for-c-api-callb for why you need to use a extern "C"
The correct way would be somthing like this:
HANDLE CPlugin::CreateWinampThread() ||
{ __VVVVVVVV__
hWinampThreadHandle = (HANDLE)CreateThread(NULL, 0, ::StartWinampThread, (void*)this, 0, &dwWinampThreadID);
if (!hWinampThreadHandle)
return 0;
CloseHandle(hWinampThreadHandle);
return hWinampThreadHandle;
}
.
// A callback function for C code must have C linkage.
// That is not possable for C++ static member functions.
extern "C" DWORD WINAPI StartWinampThread(void* lpParam)
{
// You can always call your static member function here.
CPlugin::StartWinampThread(lpParam)
}
Is it to do with objects - there's an implicit 'this' paramter to your object's StartWinampThread method because it's a member of a class.
What happens if you change it to be a standalone method but keep the same signature i.e. from
DWORD WINAPI CPlugin::StartWinampThread(void* lpParam)[...]
to
DWORD WINAPI StartWinampThread(void* lpParam)[...]
(I know it won't work for you, I'm just interested to see if it removes the compiler's complaint)