-
class problem
the following code generates error and i can't figure out why:
Code:
class ModuleManager_c
{ protected:
HANDLE hInputThread, hOutputThread;
DWORD dwInputThread, dwOutputThread;
void OutputThread(){}
void InputThread() {}
public:
ModuleManager_c(){}
~ModuleManager_c(){}
void status() {}
void start(char ** argv)
{
hInputThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)
InputThread, (LPVOID) argv[0], NULL, &dwInputThread);
}
};
yet if i put
Code:
void InputThread() {}
line outside the class it works.
Compiler output:
Code:
\server\main.cpp In member function `void ModuleManager_c::start(char**)':
\server\main.cpp argument of type `void (ModuleManager_c::)()' does not match `DWORD (*)(void*)'
\server\Makefile.win [Build Error] [main.o] Error 1
-
InputThread is a class member variable. It takes a hidden parameter "this" that is a the pointer to the current object. CreateThread has no idea about hidden parameter or the current object, so it will not be able to get that sort of information across.
It is quite possibly that you are getting errors simply because you are taking the address of a class function without an explicit address-of-operator (&), but once you get past that problem, you would still have the problem you describe.
There are several options to solve this, but they all amount to nearly the same thing: You start your thread with a function that doesn't have a hidden "this" parameter, and pass the pointer to the current object as the argument [In this case, you may have to make a struct, as you are already passing argv[0] in that place - you need both argv[0] and this].
Once in this function, you cast your void pointer back to the class object (or struct in the case described above) and call a second level thread function.
--
Mats
-
Here's what i've came up with:
Code:
class ModuleManager_c;
void OutputThread(ModuleManager_c * pModuleManager);
void InputThread(ModuleManager_c * pModuleManager );
class ModuleManager_c
{ protected:
HANDLE hInputThread, hOutputThread;
DWORD dwInputThread, dwOutputThread;
public:
int test;
ModuleManager_c(){test=17;}
~ModuleManager_c(){}
void status() {}
void start( ModuleManager_c * pModuleManager )
{
hInputThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)
InputThread, (LPVOID) pModuleManager, NULL, &dwInputThread);
}
};
void InputThread(ModuleManager_c * pModuleManager ) {cout<<pModuleManager->test; }
void OutputThread(ModuleManager_c * pModuleManager) {}
Yet i can't acces protected content.
-
A few comments:
1. Assuming that start is called something like this:
Code:
ModuleManager_c mgr;
mgr.tart(&mgr);
(As opposed to
Code:
ModuleManager_c mgr;
ModuleManager_c a;
...
mgr.start(&a)
)
then I'd suggest that you remove the pModuleManager and use "this" instead.
As for using protected content, that's where you need to have a member function as well as a non-member function, e.g:
Code:
class ModuleManager_c
{
...
private:
int test;
...
public:
void showTest() { cout << test; }
...
};
void InputThread(ModuleManager_c * pModuleManager ) {cout<<pModuleManager->showTest(); }
[The above is not complete, I've only posted the lines that are changed versus your original code, and enough original code to see where it's changed].
--
Mats
-
Ok, thanks matsp. I think it's ok now:
Code:
class ModuleManager_c;
void OutputThread(ModuleManager_c * pModuleManager);
void InputThread(ModuleManager_c * pModuleManager );
class ModuleManager_c
{ protected:
HANDLE hInputThread, hOutputThread;
DWORD dwInputThread, dwOutputThread;
int test;
public:
ModuleManager_c(){test=17;}
~ModuleManager_c(){}
void ShowTest() {cout<<test;}
void Status() {}
void Start()
{
hInputThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)
InputThread, (LPVOID) this, NULL, &dwInputThread);
}
};
void InputThread(ModuleManager_c * pModuleManager ) {pModuleManager->ShowTest(); }
void OutputThread(ModuleManager_c * pModuleManager) {}
-
Ok, so technically (sorry for not pointing that out before), you should have a void * parameter to your InputThread function, as that is how it is being called from the thread creation function.
You should then do something like this:
Code:
void InputThread(void *pArg )
{
ModuleManager_c * pModuleManager = reinterpret_cast<ModuleManager_c *>(pArg);
pModuleManager->ShowTest();
}
That way, you should be able to take off the (LPTHREAD_START_ROUTINE) cast in the CreateThread function.
Also be aware that if you call C library functions (e.g. using cout << x), you should use _beginthread or _beginthreadex(), as otherwise, you will leak resources when the thread is terminated.
--
Mats
-
Code:
class ModuleManager_c;
unsigned __stdcall ModuleManagerOutputThread(void* pArg );
unsigned __stdcall ModuleManagerInputThread(void* pArg );
class ModuleManager_c
{ protected:
HANDLE hInputThread, hOutputThread;
DWORD dwInputThread, dwOutputThread;
unsigned InputThreadID;
public:
ModuleManager_c(){}
~ModuleManager_c(){}
void Status() {}
void Start()
{
hInputThread =(HANDLE) _beginthreadex(NULL,0, &ModuleManagerInputThread,
(LPVOID) this, NULL, &InputThreadID);
}
};
unsigned __stdcall ModuleManagerInputThread(void* pArg )
{ ModuleManager_c * pModuleManager = reinterpret_cast<ModuleManager_c *>(pArg);
return 0;
}
unsigned __stdcall ModuleManagerOutputThread(void * pArg){ return 0; }
Any other mistakes?
-
Yes, that looks about right.
--
Mats
-