create thread in class - c++

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.

Related

Thread call library function with parameter

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;

C++ Visual Studio 2015 “non-standard syntax; use '&' to create a pointer to member”

I work with TaskScheduler COM, this is my code:
typedef HRESULT(*FuncOfBoll)(_Out_ VARIANT_BOOL* b);
static bool GetBool(FuncOfBoll func)
{
VARIANT_BOOL b = VARIANT_FALSE;
HRESULT hr = func(&b);
if (FAILED(hr)) return FALSE;
return b == VARIANT_TRUE;
}
void test(ITaskSettings* settings)
{
bool b = GetBool(settings->get_StopIfGoingOnBatteries); // <= The error here
// ...
}
and I get the following error:
Error C3867 'ITaskSettings::get_StopIfGoingOnBatteries': non-standard
syntax; use '&' to create a pointer to member
What is my mistake and how to correct it?
I am guessing that get_StopIfGoingOnBatteries is a member function ofITaskSettings. Such a function cannot be used when the expected argument type is FuncOfBoll. You'll need to create a wrapper function and use it.
ITaskSettings* currentSetttings = NULL;
HRESULT GetBoolWrapper(_Out_ VARIANT_BOOL* b)
{
return currentSetttings->get_StopIfGoingOnBatteries(b);
}
void test(ITaskSettings* settings)
{
currentSetttings = settings;
bool b = GetBool(GetBoolWrapper);
}
The correct definition for a pointer to member function is:
typedef HRESULT(ITaskSettings::*FuncOfBoll)(_Out_ VARIANT_BOOL* b);
Then, you should pass the pointer to the object instance to function GetBool:
static bool GetBool(ITaskSettings* setting, FuncOfBoll func)
{
VARIANT_BOOL b = VARIANT_FALSE;
HRESULT hr = (setting->*func)(&b);
...
}
Or, with template:
template<class C>
static bool GetBool(C* p, HRESULT(C::*func)(_Out_ VARIANT_BOOL*))
{
VARIANT_BOOL b = VARIANT_FALSE;
HRESULT hr = (p->*func)(&b);
...
}
Invocation:
void test(ITaskSettings* settings)
{
currentSetttings = settings;
bool b = GetBool(settings, &ITaskSettings::mb_function);
}
This is not really an answer, the question as written doesn't admit an answer, but this is too long & detailed for comment.
You don't show a full examples, so there has to be guesswork.
Apparently, judging by the error message, settings is a pointer to class type object, where that class has a member function get_StopIfGoingOnBatteries.
And apparently, judging by the use of -> operator, it's a non-static member function. You could still use -> if it were static, but that would be unnatural. So let's say it's a non-static member function.
Then you can't easily form a raw pointer to function that calls that member function, because you need a this-pointer for the call. It could just use a dummy object, if creation of such object is cheap, or it could use a global instance or pointer to instance. But better change something in your design, and/or explain more clearly what you want.

c++ Modify drivers, got "cannot convert from overloaded function" error

Im modifiy my display drivers to get update notifcation sent from the USB port. So far so good, but i got stock on follow:
GPEFlat::GPEFlat()
{
PBOOT_ARGS args;
ULONG fbSize;
ULONG fbOffset;
ULONG offsetX;
ULONG offsetY;
BOOL bFoundArgs = FALSE;
BOOL m_MouseDisabled = TRUE;
HANDLE m_hAttachEvent = CreateEvent(NULL, FALSE, FALSE, L"MouseAttached");
HANDLE m_hDetachEvent = CreateEvent(NULL, FALSE, FALSE, L"MouseDetached");
HANDLE m_hCursorThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MouseEventThread, NULL, 0, NULL);
DWORD
GPEFlat::MouseEventThread(void)
{
DWORD rc = TRUE;
HANDLE handles[2];
handles[0] = m_hAttachEvent;
handles[1] = m_hDetachEvent;
The resulting error is:
Error 1 error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'LPTHREAD_START_ROUTINE' drivers\display\vgaflat
So the line : HANDLE m_hCursorThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MouseEventThread, NULL, 0, NULL);
Dosnt work. Got some pointers that it may be to non static method.
How should i do this?
Greetings
The thing to understand is that functions (including static methods) and non-static methods are different things. CreateEvent expects a function. You must give it that, it will not work with GPEFlat::MouseEventThread because that's a method. What you can do though is give it a function which calls GPEFlat::MouseEventThread. Usually this is done like this
DWORD WINAPI thread_starter(LPVOID that)
{
return ((GPEFlat*)that)->MouseEventThread();
}
...
CreateThread(NULL, 0, thread_starter, this, 0, NULL);
Note that I pass this to CreateThread, that's very important. CreateThread passes it to the parameter that in thread_starter, which uses that to call the method you wanted to call all along.
The MouseEventThread have to be a static function, because a function pointer is not the same as a member function pointer. Static methods can be used as normal function pointers, but non-static member functions can not.
If you need to reference class members, then one very simple solution is to have a static wrapper functions, which takes the instance of the object (this in the constructor) and then calls the actual member function using that instance pointer.
Something like
class GPEFlat
{
// ...
private:
static DWORD MouseEventThreadWrapper(LPVOID instance)
{ return reinterpret_cast<GPEFlat*>(instance)->MouseEventThread(); }
// ...
};
Create the thread with this wrapper function instead, passing this as argument to it:
GPEFlat::GPEFlat()
{
// ...
HANDLE m_hCursorThread = CreateThread(
NULL, 0, (LPTHREAD_START_ROUTINE)MouseEventThreadWrapper, this, 0, NULL);
}

Error of argument type with _beginthreadex

To define my thread I have in my Header file:
class HttpClient
{
public:
...
unsigned int __stdcall PerformLogin(void*);
...
};
Then in my cpp file I have:
unsigned int __stdcall PerformLogin(void*){
...
}
And to call this thread I use
hThread = (HANDLE)_beginthreadex( NULL, 0, &PerformLogin, NULL, 0, &threadID );
But i Have an error on the &PerformLogin saying that:
the args of type unsigned int (__stdcall HttpClient::)(void) is not compatible with the param unsigned int (__stdcall*)(void*).
I understand the error, but I really don't know how to fix this!
A possible way to fix this would be to make the member function static, though this means PerformLogin() does not have a this pointer and would have no access to non-static members of HttpClient.
Another is to move PerformLogin() out of HttpClient altogether, and make it a free function.
What I usually to is to add 'this' as the void* parameter to the static function - you can then call methods on it in the static function with a bit of casting..
Member functions get this pointer implicitly as a first parameter.
So if you want to start a thread with a class member function, you should explicitly pass a pointer to a class instance in your call to _beginthreadex.
So, remove explicit argument:
class HttpClient
{
public:
...
unsigned int __stdcall PerformLogin();
...
};
And call _beginthreadex while passing this as an argument:
hThread = (HANDLE)_beginthreadex( NULL, 0, &PerformLogin, this, 0, &threadID );
It's worth mentioning that this is a bit hacky. C++ FAQ advises against it.
I still prefer this approach. Of course I just use boost::thread usually.

no instance of overloaded function "AfxBeginThread" matches the argument list

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