C++ - Thread - Pointer to function!

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • fantasticamir
    New Member
    • Apr 2007
    • 42

    C++ - Thread - Pointer to function!

    Guys,

    I have a problem which takes me 2 days to solve so far, hope you may help me.

    I have posted a thread before about it but unfortunately the problem is still there!!



    -----
    the problem is simply "I do not know what is the correct syntax if I want to call a function in POSIX thread create which has an argument which is pointer to function".

    Code:
    class EventInterface {
       public:
         EventInterface(void (*ptToFunc)(Event *, int));
         .....
         static void * receiveEvent (void (*onMessageFunc)(Event *, int));
    
    }
           
       EventInterface::EventInterface(void (*ptToFunc)(char *, int)){
    
                pthread_create( &receiveThread, NULL, EventInterface::receiveEvent, (void *) (*ptToFunc))    ?????
              ....
     
          }
    
       void EventInterface::receiveEvent(void (*onMessageFunc)(Event *, int)){
       .....
    
        onMessageFunc(notifiedEvent , subscriptionID);
        }
    I really have no idea, I almost check all of possible syntaxes but they do not work...

    The errors I received are basically because of the syntax faults. (mostly concerning the "invalid conversion from ....")

    Thanks,

    Amir.
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    Your problem is the function pointer.

    For Windows, your thread function you supply to CreateThread must be:
    [code=cpp]
    DWORD WINAPI THreadProc(LPVO ID);
    [/code]

    You can write any function BUT the function must have an LPVOID argument and return a DWORD. If it doesn't, then it can't be used as a thread.

    Read the pthread_create( ) documentation clearly and focus on the type of function pointer required. You may need to type cast your function to the correct type.

    Comment

    • fantasticamir
      New Member
      • Apr 2007
      • 42

      #3
      Originally posted by weaknessforcats
      Your problem is the function pointer.

      For Windows, your thread function you supply to CreateThread must be:
      [code=cpp]
      DWORD WINAPI THreadProc(LPVO ID);
      [/cpp]

      You can write any function BUT the function must have an LPVOID argument and return a DWORD. If it doesn't, then it can't be used as a thread.

      Read the pthread_create( ) documentation clearly and focus on the type of function pointer required. You may need to type cast your function to the correct type.
      I am working with linux.

      I just have one question: what is the correct syntax to call a method with function pointer as an argument in pthered_create?

      Comment

      • fantasticamir
        New Member
        • Apr 2007
        • 42

        #4
        forexample when I define this like:

        pthread_create( &receiveThre ad, NULL, EventInterface: :receiveEvent, (void *) (*ptToFunc))

        or

        pthread_create( &receiveThre ad, NULL, EventInterface: :receiveEvent, (void *) ptToFunc)


        I have this error:

        error: invalid conversion from 'void* (*)(void (*)(Event*, int))' to 'void* (*)(void*)'

        Comment

        • weaknessforcats
          Recognized Expert Expert
          • Mar 2007
          • 9214

          #5
          pthread_create has this prototype:

          [code=c]
          int pthread_create( pthread_t *thread, const pthread_attr_t *attr,
          void *(*start_routin e)(void*), void *arg);

          [/code]

          The start routine is:

          void *(*start_routin e)(void*)

          That is, start_routine is a pointer to a function with a void* argunment that returns a void*.

          Your function must have thisprototype.

          However, this function:
          [code=c]
          void (*ptToFunc)(Eve nt *, int));
          [/code]

          does not have a void* argument and does not return a void*. So you can't use this function as a thread.

          Yout could use:
          [code=c]
          void *MyFunction(voi d*);
          [/code]

          This is exactly the procedure I outlined in the Windows eaxmple. The OS function cannot accommodate just any old function. It has to be of a pre-defined format.

          Inside MyFunction(void * arg) you know the arg is an Event* so it is safe to type cast the void* to an Event* and off you go.

          Comment

          • fantasticamir
            New Member
            • Apr 2007
            • 42

            #6
            I guess I find a way to solve the problem.


            Code:
             class EventInterface {
                        public:
            		typedef void (*onMessageFunction)(Event*, int);
            
            
            		EventInterface(onMessageFunction);
             	
            	}
            	
            	    EventInterface::EventInterface(onMessageFunction pt2Func){
             
                              pthread_create( &receiveThread, NULL, EventInterface::receiveEvent, (void *) pt2Func)                   *
             
                    }
            
                   void EventInterface::receiveEvent(void * arg){
            	
            	  onMessageFunction onMessageFunc;                               *
                      onMessageFunc= (onMessageFunction) arg;		
             
                      onMessageFunc(notifiedEvent , subscriptionID);
                   }
            However now I see some warning like:

            ISO C++ forbids casting between pointer-to-function and pointer-to-object

            for those lines I showed by *.

            Do you have any idea?

            Comment

            • weaknessforcats
              Recognized Expert Expert
              • Mar 2007
              • 9214

              #7
              Did you read Post #5??

              Comment

              • fantasticamir
                New Member
                • Apr 2007
                • 42

                #8
                Originally posted by weaknessforcats
                Did you read Post #5??
                actually I read that after I post my new post!

                The problem is the name of call back function is called from EventInterface constructor. so how could it be possible with your solution?!

                maybe I need to read your solution more accurately.

                Comment

                • fantasticamir
                  New Member
                  • Apr 2007
                  • 42

                  #9
                  for those who might see this thread then... I finally come up with a syntax which WORKS!

                  I just wrap my pointer to function in an struct!\

                  Code:
                  class EventInterface 
                  {
                  
                  public:
                  
                  	typedef struct{
                  		void (*onMessageFunction)(Event*, int);
                  	} callBackFunc;
                  
                  	EventInterface(callBackFunc);
                          ...
                  	static void * receiveEvent (void *);
                  
                  }
                  
                  EventInterface::EventInterface(callBackFunc ptToFunc){
                   
                  	pthread_create( &receiveThread, NULL, EventInterface::receiveEvent, (void *) &ptToFunc)
                  	
                  }
                  
                  void * EventInterface::receiveEvent(void * arg){
                  	
                  	callBackFunc * onMessageFunc;
                  	onMessageFunc= (callBackFunc*) arg;
                  
                         .....
                  
                         onMessageFunc->onMessageFunction(notifiedEvent , subscriptionID);
                  }

                  Comment

                  • AdrianH
                    Recognized Expert Top Contributor
                    • Feb 2007
                    • 1251

                    #10
                    Originally posted by fantasticamir
                    for those who might see this thread then... I finally come up with a syntax which WORKS!

                    I just wrap my pointer to function in an struct!\

                    Code:
                    class EventInterface 
                    {
                    
                    public:
                    
                    	typedef struct{
                    		void (*onMessageFunction)(Event*, int);
                    	} callBackFunc;
                    
                    	EventInterface(callBackFunc);
                            ...
                    	static void * receiveEvent (void *);
                    
                    }
                    
                    EventInterface::EventInterface(callBackFunc ptToFunc){
                     
                    	pthread_create( &receiveThread, NULL, EventInterface::receiveEvent, (void *) &ptToFunc)
                    	
                    }
                    
                    void * EventInterface::receiveEvent(void * arg){
                    	
                    	callBackFunc * onMessageFunc;
                    	onMessageFunc= (callBackFunc*) arg;
                    
                           .....
                    
                           onMessageFunc->onMessageFunction(notifiedEvent , subscriptionID);
                    }
                    Don't do it. It will mess up. Get rid of the address operator. You are passing the address of where the callback pointer is stored on the stack.
                    [code=c] pthread_create( &receiveThre ad, NULL, EventInterface: :receiveEvent, (void *) ptToFunc)[/code].


                    Adrian

                    Comment

                    Working...