एक वर्ग से pthread फ़ंक्शन


86

मान लीजिए कि मेरे पास एक वर्ग है जैसे कि

class c { 
    // ...
    void *print(void *){ cout << "Hello"; }
}

और फिर मेरे पास c का वेक्टर है

vector<c> classes; pthread_t t1;
classes.push_back(c());
classes.push_back(c());

अब, मैं एक थ्रेड बनाना चाहता हूं c.print();

और निम्नलिखित मुझे नीचे समस्या दे रहा है: pthread_create(&t1, NULL, &c[0].print, NULL);

त्रुटि Ouput: 'void * (tree_item ::) (void )' को 'void * ( ) (void )' में तर्क के लिए '3' को 'int preadread_create (pthread_t *), const pthread_attr_t *, void * ( ) (void) में नहीं बदल सकते। ), शून्य *) '

जवाबों:


147

आप इसे वैसे नहीं लिख सकते, जैसा आपने लिखा है क्योंकि C ++ क्लास मेंबर फंक्शन्स में एक छिपा हुआ thisपैरामीटर पास होता है। pthread_create()इसका कोई मतलब नहीं है कि किस वैल्यू का thisइस्तेमाल किया जाए, इसलिए यदि आप फंक्शन को मेथड में कंपाइलर के आसपास लाने की कोशिश करते हैं। उपयुक्त प्रकार का पॉइंटर, आपको एक सेग्मनेशन फॉल्ट मिलेगा। आपको क्लास thisको बूटस्ट्रैप करने के लिए एक स्टैटिक क्लास मेथड (जिसमें कोई पैरामीटर नहीं है) या एक साधारण साधारण फंक्शन का उपयोग करना होगा:

class C
{
public:
    void *hello(void)
    {
        std::cout << "Hello, world!" << std::endl;
        return 0;
    }

    static void *hello_helper(void *context)
    {
        return ((C *)context)->hello();
    }
};
...
C c;
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, &c);

निम्न तरीके से वैक्टर के साथ उपरोक्त कार्य करेंगे: pthread_create (& t, NULL, & C :: hello_helper, और वेक्टर_c [0]); ?
परी.कििंग .४

उपरोक्त सभी टिप्पणियां उपयोगी हैं I मैंने किसी समस्या को हल करने के लिए सभी से एक संयोजन का उपयोग किया है .. यह अभी भी उतना ही सरल है जितना मैं इसे करने की कोशिश कर रहा था ... लेकिन दुर्भाग्य से मैं केवल एक को सही होने के रूप में चिह्नित कर सकता हूं, अन्यथा हर एक को मिल जाता है क्रेडिट..धन्यवाद
Angel.King.47

मैं इस उत्तर को आगे बढ़ाना चाहता था, लेकिन इसमें सी-स्टाइल कास्ट्स का उपयोग किया गया है, जिसे अत्यधिक पूर्वाग्रह के साथ समाप्त किया जाना चाहिए। यह उत्तर अन्यथा सही है।
क्रिस जस्टर-यंग

@ क्रिस: मैं कास्ट स्टाइल के बारे में एक पवित्र युद्ध में नहीं आना चाहता, लेकिन इस उदाहरण में सी-स्टाइल कास्ट का उपयोग करना पूरी तरह से शब्दशः सही है।
एडम रोसेनफील्ड

2
@AdamRosenfield यह भी पूरी तरह से शब्दशः एक साथ श्रृंखला क्रिया विशेषण के लिए सही है, लेकिन यह अच्छी शैली नहीं है! xD
ACK_stoverflow

82

एक धागे को संभालने का मेरा पसंदीदा तरीका यह है कि इसे C ++ ऑब्जेक्ट के अंदर एन्क्रिप्ट किया जाए। यहाँ एक उदाहरण है:

class MyThreadClass
{
public:
   MyThreadClass() {/* empty */}
   virtual ~MyThreadClass() {/* empty */}

   /** Returns true if the thread was successfully started, false if there was an error starting the thread */
   bool StartInternalThread()
   {
      return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0);
   }

   /** Will not return until the internal thread has exited. */
   void WaitForInternalThreadToExit()
   {
      (void) pthread_join(_thread, NULL);
   }

protected:
   /** Implement this method in your subclass with the code you want your thread to run. */
   virtual void InternalThreadEntry() = 0;

private:
   static void * InternalThreadEntryFunc(void * This) {((MyThreadClass *)This)->InternalThreadEntry(); return NULL;}

   pthread_t _thread;
};

इसका उपयोग करने के लिए, आप बस अपने थ्रेड के ईवेंट लूप को लागू करने के लिए लागू किए गए InternalThreadEntry () विधि के साथ MyThreadClass का एक उपवर्ग बनाएंगे। आपको थ्रेड ऑब्जेक्ट को हटाने से पहले थ्रेड ऑब्जेक्ट पर WaitForInternalThreadToExit () कॉल करने की आवश्यकता होगी, और (निश्चित रूप से थ्रेड वास्तव में बाहर निकलने के लिए सुनिश्चित करने के लिए कुछ तंत्र है, अन्यथा WaitForInternalThreadToExit () कभी नहीं लौटेगा)


1
यह एक शानदार तरीका है जो मैं उपरोक्त वर्चुअल क्लास के उपयोग को समझ सकता हूं, लेकिन मुझे बहुत अधिक समस्या है..मुझे ऐसे धागे मिलते हैं जो अन्य थ्रेड्स से बाहर निकलते हैं जिन्हें सभी को वेक्टर में डालने की आवश्यकता होती है। और फिर सभी थ्रेड्स में जाने और शामिल होने के लिए एक पुनरावर्ती लूप। मुझे यकीन है कि मैं उपरोक्त को लागू करने के लिए उचित स्थान पर प्रतीक्षा को बुलाकर लागू कर सकता हूं, लेकिन il यह देखने की कोशिश करता हूं कि मुझे कहां मिलता है
Angel.King.47

4
यह समाधान बहुत सुरुचिपूर्ण है। मैं अभी से इसका इस्तेमाल करूंगा। शुक्रिया जेरेमी फ्रेज़नर। +1
अरमाडा

हेलो जेरेमी फ्रेज़र, इंटरनलट्रेडएंट्री (aclass_ref & refobj) का एक संदर्भ कैसे पारित करें? मुझे क्या परिवर्तन करना चाहिए?
श्री

@sree एक सदस्य चर के रूप में MyThreadClass में संदर्भ (या एक सूचक) जोड़ें; इसके बाद (यह * शून्य) तर्क के माध्यम से गुजरने के बारे में चिंता किए बिना, आंतरिक रूप से (इसे) सीधे एक्सेस कर सकते हैं।
जेरेमी फ्रेज़र

10

आपको pthread_createएक फ़ंक्शन देना होगा जो उस हस्ताक्षर से मेल खाता है जिसे वह ढूंढ रहा है। जो आप कर रहे हैं वह काम नहीं करेगा।

आप ऐसा करने के लिए जो भी स्थिर फ़ंक्शन लागू कर सकते हैं, और यह एक उदाहरण का संदर्भ दे सकता है cऔर थ्रेड में जो आप चाहते हैं उसे निष्पादित कर सकते हैं। pthread_createकेवल एक फ़ंक्शन पॉइंटर लेने के लिए डिज़ाइन नहीं किया गया है, बल्कि "संदर्भ" के लिए एक पॉइंटर है। इस मामले में आप इसे केवल उदाहरण के लिए एक पॉइंटर पास करते हैं c

उदाहरण के लिए:

static void* execute_print(void* ctx) {
    c* cptr = (c*)ctx;
    cptr->print();
    return NULL;
}


void func() {

    ...

    pthread_create(&t1, NULL, execute_print, &c[0]);

    ...
}

1
ooo मैं देख रहा हूं कि आपका क्या मतलब है .. इसे ग के पॉइंटर को पास करें, gotcha .. इसे लागू करेगा और इसे
आज़माएगा

2

उपरोक्त उत्तर अच्छे हैं, लेकिन मेरे मामले में, 1 दृष्टिकोण जो फ़ंक्शन को एक स्थिर होने के लिए परिवर्तित करता है, वह काम नहीं करता है। मैं बाहर निकलने के कोड को थ्रेड फ़ंक्शन में ले जाने के लिए परिवर्तित करने की कोशिश कर रहा था, लेकिन उस कोड में गैर-स्थिर वर्ग के सदस्यों के संदर्भ पहले से ही बहुत सारे थे। C ++ ऑब्जेक्ट में एन्कैप्सुलेटिंग का दूसरा समाधान काम करता है, लेकिन एक थ्रेड को चलाने के लिए 3-स्तरीय आवरण हैं।

मेरे पास एक वैकल्पिक समाधान था जो मौजूदा सी ++ निर्माण - 'मित्र' फ़ंक्शन का उपयोग करता है, और इसने मेरे मामले के लिए एकदम सही काम किया। मैंने 'मित्र ’का उपयोग कैसे किया, इसका एक उदाहरण (उपरोक्त उदाहरण का उपयोग नामों के लिए दिखाएगा कि इसे दोस्त के रूप में कॉम्पैक्ट रूप में कैसे बदला जा सकता है)

    class MyThreadClass
    {
    public:
       MyThreadClass() {/* empty */}
       virtual ~MyThreadClass() {/* empty */}

       bool Init()
       {
          return (pthread_create(&_thread, NULL, &ThreadEntryFunc, this) == 0);
       }

       /** Will not return until the internal thread has exited. */
       void WaitForThreadToExit()
       {
          (void) pthread_join(_thread, NULL);
       }

    private:
       //our friend function that runs the thread task
       friend void* ThreadEntryFunc(void *);

       pthread_t _thread;
    };

    //friend is defined outside of class and without any qualifiers
    void* ThreadEntryFunc(void *obj_param) {
    MyThreadClass *thr  = ((MyThreadClass *)obj_param); 

    //access all the members using thr->

    return NULL;
    }

बेशक, हम बूस्ट :: थ्रेड का उपयोग कर सकते हैं और इन सभी से बच सकते हैं, लेकिन मैं सी + + कोड को बढ़ावा देने के लिए बढ़ावा का उपयोग नहीं करने की कोशिश कर रहा था (कोड केवल इस उद्देश्य के लिए बढ़ावा देने के खिलाफ लिंक कर रहा था)


1

इस उम्मीद में मेरा पहला जवाब कि यह किसी के लिए उपयोगी होगा: मैं अब यह एक पुराना सवाल है, लेकिन मैं उपरोक्त प्रश्न के समान त्रुटि का सामना कर रहा हूं क्योंकि मैं एक TcpServer वर्ग लिख रहा हूं और मैं pthreads का उपयोग करने का प्रयास कर रहा था। मुझे यह सवाल मिला और मुझे समझ में आया कि अब ऐसा क्यों हो रहा है। मैंने यह करना समाप्त कर दिया:

#include <thread>

थ्रेडेड चलाने की विधि -> void* TcpServer::sockethandler(void* lp) {/*code here*/}

और मैं इसे मेमने के साथ कहता हूं -> std::thread( [=] { sockethandler((void*)csock); } ).detach();

यह मेरे लिए एक साफ दृष्टिकोण है।


0

बहुत बार मैंने यह हल करने के तरीके खोजे हैं कि आप उससे क्या पूछ रहे हैं, मेरी राय में यह बहुत जटिल है। उदाहरण के लिए आपको नए प्रकार के प्रकार, लिंक लाइब्रेरी आदि को परिभाषित करना है, इसलिए मैंने कोड की कुछ पंक्तियों को लिखने का फैसला किया है, जो अंतिम उपयोगकर्ता को मूल रूप से "थ्रेड-आइज़" को "शून्य :: विधि (शून्य)" में सक्षम करने की अनुमति देता है। जो भी वर्ग। यह सुनिश्चित करने के लिए कि इस समाधान को मैंने लागू किया है, बढ़ाया जा सकता है, बेहतर किया जा सकता है, आदि, इसलिए, यदि आपको अधिक विशिष्ट तरीकों या विशेषताओं की आवश्यकता है, तो उन्हें जोड़ें और कृपया मुझे लूप में रखने के लिए बहुत दयालु बनें।

यहाँ 3 फाइलें हैं जो दिखाती हैं कि मैंने क्या किया।

    // A basic mutex class, I called this file Mutex.h
#ifndef MUTEXCONDITION_H_
#define MUTEXCONDITION_H_

#include <pthread.h>
#include <stdio.h>

class MutexCondition
{
private:
    bool init() {
        //printf("MutexCondition::init called\n");
        pthread_mutex_init(&m_mut, NULL);
        pthread_cond_init(&m_con, NULL);
        return true;
    }

    bool destroy() {
        pthread_mutex_destroy(&m_mut);
        pthread_cond_destroy(&m_con);
        return true;
    }

public:
    pthread_mutex_t m_mut;
    pthread_cond_t m_con;

    MutexCondition() {
        init();
    }
    virtual ~MutexCondition() {
        destroy();
    }

    bool lock() {
        pthread_mutex_lock(&m_mut);
        return true;
    }

    bool unlock() {
        pthread_mutex_unlock(&m_mut);
        return true;
    }

    bool wait() {
        lock();
        pthread_cond_wait(&m_con, &m_mut);
        unlock();
        return true;
    }

    bool signal() {
        pthread_cond_signal(&m_con);
        return true;
    }
};
#endif
// End of Mutex.h

// वह विधि जो किसी कार्य को थ्रेड-ize करने के लिए सभी कार्य को बाधित करती है (test.h):

#ifndef __THREAD_HANDLER___
#define __THREAD_HANDLER___

#include <pthread.h>
#include <vector>
#include <iostream>
#include "Mutex.h"

using namespace std;

template <class T> 
class CThreadInfo
{
  public:
    typedef void (T::*MHT_PTR) (void);
    vector<MHT_PTR> _threaded_methods;
    vector<bool> _status_flags;
    T *_data;
    MutexCondition _mutex;
    int _idx;
    bool _status;

    CThreadInfo(T* p1):_data(p1), _idx(0) {}
    void setThreadedMethods(vector<MHT_PTR> & pThreadedMethods)
    {
        _threaded_methods = pThreadedMethods;
      _status_flags.resize(_threaded_methods.size(), false);
    }
};

template <class T> 
class CSThread {
  protected:
    typedef void (T::*MHT_PTR) (void);
    vector<MHT_PTR> _threaded_methods;
    vector<string> _thread_labels;
    MHT_PTR _stop_f_pt;
    vector<T*> _elements;
    vector<T*> _performDelete;
    vector<CThreadInfo<T>*> _threadlds;
    vector<pthread_t*> _threads;
    int _totalRunningThreads;

    static void * gencker_(void * pArg)
    {
      CThreadInfo<T>* vArg = (CThreadInfo<T> *) pArg;
      vArg->_mutex.lock();
      int vIndex = vArg->_idx++;
      vArg->_mutex.unlock();

      vArg->_status_flags[vIndex]=true;

      MHT_PTR mhtCalledOne = vArg->_threaded_methods[vIndex];
      (vArg->_data->*mhtCalledOne)();
      vArg->_status_flags[vIndex]=false;
        return NULL;
    }

  public:
    CSThread ():_stop_f_pt(NULL), _totalRunningThreads(0)  {}
    ~CSThread()
    {
      for (int i=_threads.size() -1; i >= 0; --i)
          pthread_detach(*_threads[i]);

      for (int i=_threadlds.size() -1; i >= 0; --i)
        delete _threadlds[i];

      for (int i=_elements.size() -1; i >= 0; --i)
         if (find (_performDelete.begin(), _performDelete.end(), _elements[i]) != _performDelete.end())
              delete _elements[i];
    }
    int  runningThreadsCount(void) {return _totalRunningThreads;}
    int  elementsCount()        {return _elements.size();}
    void addThread (MHT_PTR p, string pLabel="") { _threaded_methods.push_back(p); _thread_labels.push_back(pLabel);}
    void clearThreadedMethods() { _threaded_methods.clear(); }
    void getThreadedMethodsCount() { return _threaded_methods.size(); }
    void addStopMethod(MHT_PTR p)  { _stop_f_pt  = p; }
    string getStatusStr(unsigned int _elementIndex, unsigned int pMethodIndex)
    {
      char ch[99];

      if (getStatus(_elementIndex, pMethodIndex) == true)
        sprintf (ch, "[%s] - TRUE\n", _thread_labels[pMethodIndex].c_str());
      else 
        sprintf (ch, "[%s] - FALSE\n", _thread_labels[pMethodIndex].c_str());

      return ch;
    }
    bool getStatus(unsigned int _elementIndex, unsigned int pMethodIndex)
    {
      if (_elementIndex > _elements.size()) return false;
      return _threadlds[_elementIndex]->_status_flags[pMethodIndex];
    }

    bool run(unsigned int pIdx) 
    {
      T * myElem = _elements[pIdx];
      _threadlds.push_back(new CThreadInfo<T>(myElem));
      _threadlds[_threadlds.size()-1]->setThreadedMethods(_threaded_methods);

      int vStart = _threads.size();
      for (int hhh=0; hhh<_threaded_methods.size(); ++hhh)
          _threads.push_back(new pthread_t);

      for (int currentCount =0; currentCount < _threaded_methods.size(); ++vStart, ++currentCount)
      {
                if (pthread_create(_threads[vStart], NULL, gencker_, (void*) _threadlds[_threadlds.size()-1]) != 0)
        {
                // cout <<"\t\tThread " << currentCount << " creation FAILED for element: " << pIdx << endl;
                    return false;
                }
        else
        {
            ++_totalRunningThreads;
             // cout <<"\t\tThread " << currentCount << " creation SUCCEDED for element: " << pIdx << endl;
                }
      }
      return true;
    }

    bool run() 
    {
            for (int vI = 0; vI < _elements.size(); ++vI) 
            if (run(vI) == false) return false;
          // cout <<"Number of currently running threads: " << _totalRunningThreads << endl;
        return true;
    }

    T * addElement(void)
    {
      int vId=-1;
      return addElement(vId);
    }

    T * addElement(int & pIdx)
    {
      T * myElem = new T();
      _elements.push_back(myElem);
      pIdx = _elements.size()-1;
      _performDelete.push_back(myElem);
      return _elements[pIdx];
    }

    T * addElement(T *pElem)
    {
      int vId=-1;
      return addElement(pElem, vId);
    }

    T * addElement(T *pElem, int & pIdx)
    {
      _elements.push_back(pElem);
      pIdx = _elements.size()-1;
      return pElem;
    }

    T * getElement(int pId) { return _elements[pId]; }

    void stopThread(int i)  
    {
      if (_stop_f_pt != NULL) 
      {
         ( _elements[i]->*_stop_f_pt)() ;
      }
      pthread_detach(*_threads[i]);
      --_totalRunningThreads;
    }

    void stopAll()  
    {
      if (_stop_f_pt != NULL) 
        for (int i=0; i<_elements.size(); ++i) 
        {
          ( _elements[i]->*_stop_f_pt)() ;
        }
      _totalRunningThreads=0;
    }
};
#endif
// end of test.h

// एक उपयोग उदाहरण फ़ाइल "test.cc" है कि लाइनक्स पर मैंने उस कक्षा के साथ संकलित किया है जो किसी कार्य को थ्रेड-ize करने के लिए सभी कार्य को बाधित करता है: g ++ -o mytest.exe test.cc -I। -Lpreadread -lstdc ++

#include <test.h>
#include <vector>
#include <iostream>
#include <Mutex.h>

using namespace std;

// Just a class for which I need to "thread-ize" a some methods
// Given that with OOP the objecs include both "functions" (methods)
// and data (attributes), then there is no need to use function arguments,
// just a "void xxx (void)" method.
// 
class TPuck
{
  public:
   bool _go;
   TPuck(int pVal):_go(true)
   {
     Value = pVal;
   }
   TPuck():_go(true)
   {
   }
   int Value;
   int vc;

   void setValue(int p){Value = p; }

   void super()
   {
     while (_go)
     {
      cout <<"super " << vc << endl;
            sleep(2);
         }
      cout <<"end of super " << vc << endl;
   }

   void vusss()
   {
     while (_go)
     {
      cout <<"vusss " << vc << endl;
      sleep(2);
     }
      cout <<"end of vusss " << vc << endl;
   }

   void fazz()
   {
     static int vcount =0;
     vc = vcount++;
     cout <<"Puck create instance: " << vc << endl;
     while (_go)
     {
       cout <<"fazz " << vc << endl;
       sleep(2);
     }
     cout <<"Completed TPuck..fazz instance "<<  vc << endl;
   }

   void stop()
   {
      _go=false;
      cout << endl << "Stopping TPuck...." << vc << endl;
   }
};


int main(int argc, char* argv[])
{
  // just a number of instances of the class I need to make threads
  int vN = 3;

  // This object will be your threads maker.
  // Just declare an instance for each class
  // you need to create method threads
  //
  CSThread<TPuck> PuckThreadMaker;
  //
  // Hera I'm telling which methods should be threaded
  PuckThreadMaker.addThread(&TPuck::fazz, "fazz1");
  PuckThreadMaker.addThread(&TPuck::fazz, "fazz2");
  PuckThreadMaker.addThread(&TPuck::fazz, "fazz3");
  PuckThreadMaker.addThread(&TPuck::vusss, "vusss");
  PuckThreadMaker.addThread(&TPuck::super, "super");

  PuckThreadMaker.addStopMethod(&TPuck::stop);

  for (int ii=0; ii<vN; ++ii)
  {
    // Creating instances of the class that I need to run threads.
    // If you already have your instances, then just pass them as a
    // parameter such "mythreadmaker.addElement(&myinstance);"
    TPuck * vOne = PuckThreadMaker.addElement();
  }

  if (PuckThreadMaker.run() == true)
  {
    cout <<"All running!" << endl;
  }
  else
  {
    cout <<"Error: not all threads running!" << endl;
  }

  sleep(1);
  cout <<"Totale threads creati: " << PuckThreadMaker.runningThreadsCount()  << endl;
  for (unsigned int ii=0; ii<vN; ++ii)
  {
    unsigned int kk=0;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl; 
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl; 
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl; 
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl; 
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl; 
  }

  sleep(2);
  PuckThreadMaker.stopAll();
  cout <<"\n\nAfter the stop!!!!" << endl;
  sleep(2);

  for (int ii=0; ii<vN; ++ii)
  {
    int kk=0;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl; 
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl; 
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl; 
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl; 
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl; 
  }

  sleep(5);
  return 0;
}

// End of test.cc

0

यह थोड़ा पुराना सवाल है लेकिन एक बहुत ही सामान्य मुद्दा है जो कई मुद्दों का सामना करता है। इसके बाद std :: thread का उपयोग करके इसे संभालने का एक सरल और सुरुचिपूर्ण तरीका है

#include <iostream>
#include <utility>
#include <thread>
#include <chrono>

class foo
{
    public:
        void bar(int j)
        {
            n = j;
            for (int i = 0; i < 5; ++i) {
                std::cout << "Child thread executing\n";
                ++n;
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        }
        int n = 0;
};

int main()
{
    int n = 5;
    foo f;
    std::thread class_thread(&foo::bar, &f, n); // t5 runs foo::bar() on object f
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
    std::cout << "Main Thread running as usual";
    class_thread.join();
    std::cout << "Final value of foo::n is " << f.n << '\n';
}

उपरोक्त कोड थ्रेड फ़ंक्शन को पास करने के तर्क का भी ध्यान रखता है।

देखें std :: धागा अधिक जानकारी के लिए दस्तावेज़।


-1

मेरा अनुमान है कि यह b / c होगा, जो कि C ++ b / c द्वारा थोड़ा बढ़ा हुआ है, इसे C ++ पॉइंटर भेजने वाला है, न कि C फंक्शन पॉइंटर। जाहिरा तौर पर एक अंतर है । ए करने की कोशिश करो

(void)(*p)(void) = ((void) *(void)) &c[0].print; //(check my syntax on that cast)

और फिर पी भेज रहा हूं।

मैंने वही किया है जो आपके सदस्य कार्य के साथ भी कर रहा है, लेकिन मैंने इसे उस कक्षा में किया था जो इसका उपयोग कर रहा था, और एक स्थिर फ़ंक्शन के साथ - जो मुझे लगता है कि अंतर बना।


मैंने ऊपर की कोशिश की, लेकिन इसके मुझे सिंटैक्स त्रुटियां दीं .. इसे आसपास भी बदलने की कोशिश की ... यदि आप यह दिखाने के लिए पर्याप्त होंगे कि pthread_create (...) का उपयोग करना उपयोगी हो सकता है
Angel.King.47

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.