   [C++]Pass member function to _beginthread()
  Hello.I have a problem with a function. First of all the function:void __cdecl CallWritingThread(void *);This function is a member of my classclass CLogSystemThe problem is, when I want to write for example an error to a file, I want to do this by a seperate thread.So I want to start the new thread with the function which writes this message into this file. So I start the thread by _beginthread(*startAdress, stackSize, Param)The parameter must be a pointer to the thread proc with this notation:void (*thread)(void *)As you can see, the function which I posted first, has this structure.When I write:_beginthread(CallWritingThread, 0, NULL);The compiler says:'CLogSystem::CallWritingThread': function call missing argument list; use '&CLogSystem::CallWritingThread' to create a pointer to memberSo I listened to it and wrote this:_beginthread(&CLogSystem::CallWritingThread, 0, NULL);But the compiler picked at this code again with that:'_beginthread' : cannot convert parameter 1 from 'void (__cdecl CLogSystem::* )(void *)' to 'void (__cdecl *)(void *)'I absolutly don´t know what the compiler want!?Please helpAlex    
  Pointers to non-static member functions (void (Foo::*)()) are not compatible with 'regular' function pointers (void (*)()). Therefore, you cannot pass them to a C API, like the Win32 API.What you need to do is write a normal (non-member or static member) function taking a void* parameter (_beginthread() allows that), and in that function cast the parameter back to the proper object pointer type and use it to call whichever member function it is you wanted to call in the first place. Then in _beginthread, you pass the pointer as void* user data:class Foo{public:   void doit() { /* ... */ }   static void call_doit(void* ptr)   { reinterpret_cast<Foo*>(ptr)->doit();   }};int main(){   Foo f;   _beginthread(&Foo::doit_, 0, &f);};  Thanks for that fast response!Is there any other solution? I mean the cast.The class  CLogSystem : public CSingletonis derived from a singleton class.And I can say, that I have declared one in the main file.So can I use this singleton object of the class CLogSystem for this?The problem is that I want to hold the functionality togehter.Alex   ;Quote:Original post by directNoobIs there any other solution? I mean the cast.No. _beginthread work with a void*, you will need the cast.Quote:So can I use this singleton object of the class CLogSystem for this?If you have a singleton, then of course, you don't need to pass the object pointer to _beginthread, you can just retrieve it in the function itself. But then again, if you have a fscking singleton, why do you need a member function? It doesn't buy you anything except complications.Quote:The problem is that I want to hold the functionality togehter.Keeping things together in the same file is often sufficient. It doesn't all have to be in a single class. Namespaces can help, too.;  If you're using a singleton (fscking is right Fruny lol) why not make the function static... You're entire class basically is.   ;  Hi.Now everything is working just fine. But first I wanted to use a html file for capturing the msgs. But nothing worked, it worked but not well. Now I use a .txt file and the next problem occures. The problem is that the escape sequences \n and \r don´t work, but \t for example works.I use the way with the handles. this means, I use CreateFile() andWriteFile()Furthermore, I use wide characters.What can I do now?Alex[Edited by - directNoob on June 18, 2006 7:31:05 AM];  What if it were not a static class, and the passed function should know about its parent. I mean that the function taking a function pointer should be general to take both normal function and member together.SORRY FOR HIJACKING THE THREAD :)   ;  This should show you a simple way to make a thread call a member function using a static function and sending the instance as a parameter to the _beginthread function. This is some ugly code I just hacked together (haven't been using C++ for a while) which should not be used directly as it is, but you get the general idea. The Sleep calls are there to make sure the printing doesn't collide - so as I said uglyuglyugly ;)#include <windows.h>#include <iostream>#include <process.h>class TestBase{protected:std::ostream* m_pos;public:TestBase(std::ostream* pos) { m_pos = pos; }virtual ~TestBase() { }virtual void Print() = 0;static void Caller(void* param){TestBase* tb = (TestBase*)param;tb->Print();delete tb;}};class TestClass : public TestBase{public:TestClass(std::ostream* pos) : TestBase(pos) { }void Print() { (*m_pos) << "Test" << std::endl; }};class TestClassX : public TestBase{public:TestClassX(std::ostream* pos) : TestBase(pos) { }void Print() { (*m_pos) << "TestXXX" << std::endl; }};int main(){TestBase* a = new TestClass(&std::cout);TestBase* b = new TestClassX(&std::cout);_beginthread(TestBase::Caller, 0, (void*)a);Sleep(1000);_beginthread(TestBase::Caller, 0, (void*)b);Sleep(1000);return 0;}arithma:You could make a new function that takes a functor as a parameter instead of a function pointer. This implementation of the functor is a modified version of the one in the enginuity series. I've added a void* parameter to pass them the parameters from the beginthread function. (This code is also a quick hack, but I guess you get the point):Modified functorclass Functor{   public: virtual void operator ()(void* args) const =0; virtual ~Functor() { }};template<class T>class ClassFunctor : public Functor{   protected: typedef void (T::*FuncType)(void* args); T* m_obj; FuncType m_func;   public: ClassFunctor(T *o, FuncType f): m_obj(o), m_func(f) { }    void operator ()(void* args) const {    (m_obj->*m_func)(args); }};class FunctionFunctor : public Functor{   protected: typedef void (*FuncType)(void* args); FuncType m_func;   public: FunctionFunctor(FuncType f): m_func(f) { }    void operator ()(void* args) const {    (*m_func)(args); }};BeginThreadstruct FunctDataPair{   const Functor* pFunctor;   void* argList;};void FunctorCaller(void *arglist){   FunctDataPair* data = (FunctDataPair*)(arglist);   (*data->pFunctor)(data->argList);   delete data;}void BeginThread(const Functor* ftor, unsigned int stackSize, void *argList){   FunctDataPair* data = new FunctDataPair();   data->pFunctor = ftor;   data->argList = argList;   _beginthread(FunctorCaller, stackSize, (void*)data);}Testclass TestClass{   private: std::string m_text;   public: TestClass(const std::string& text)    : m_text(text) { } void Print(void* args) {    std::cout << m_text.c_str() << " - " << (int)args << std::endl; }};void SomeFunction(void* args){   std::cout << "::SomeFunction - " << (int)args << std::endl;}int main(){   TestClass tc("TestClass::Print");   ClassFunctor<TestClass> cf(&tc, &TestClass::Print);   FunctionFunctor ff(SomeFunction);   BeginThread(&cf, 0, (void*)1234);   Sleep(1000);   BeginThread(&ff, 0, (void*)7654);   Sleep(1000);   return 0;} [Edited by - e-u-l-o-g-y on June 18, 2006 10:38:09 AM];Quote:Original post by arithmaWhat if it were not a static class, and the passed function should know about its parent. I mean that the function taking a function pointer should be general to take both normal function and member together.It cannot. The windows API is a C API. C knows nothing about pointers to member functions. And it doesn't support function overloading, so you could not even have two different functions to make it work transparently.You cannot use a pointer to member where a pointer is expected, nor vice-versa.Pointers to member functions are not the same thing as regular function pointers. They do not even have the same size. They do not contain the address of the function to be called. Heck, two pointers to member might even be structured differently. Two different compilers might also implement them differently (and in fact, they often do), meaning you can't even safely pass them to a library that has been compiled with a different compiler.You cannot use a pointer to member where a pointer is expected, nor vice-versa.For more discussion of the guts of a pointer-to-member, see this article. If the article goes over your head, then just remember this:You cannot use a pointer to member where a pointer is expected, nor vice-versa.[Edited by - Fruny on June 18, 2006 11:14:27 AM];Quote:Original post by FrunyYou cannot use a pointer to member where a pointer is expected, nor vice-versa.Are you trying to say something? [grin]All this mucking about is why I use boost::thread for my MT needs [smile]   