2

*nix 平台是否支持以下内容?

    #include <cstdio>
    #include <sys/types.h>
    #include <signal.h>
    #include <unistd.h>

    class SignalProcessor
    {
     public:
      static void OnMySignal(int sig_num)
      {
          printf("Caught %d signal\n", sig_num);
          fflush(stdout);

          return;
      } 
    }; 
    using namespace std;

   int main()
   {

          signal(SIGINT,SingalProcessor::OnMySignal);
          printf("Ouch\n");

          pause();

          return 0;
   }
4

3 回答 3

5

从技术上讲,不,你不能。

您碰巧很幸运,您的编译器使用的调用约定与它用于“C”函数的调用约定相同。由于未定义 C++ ABI,下一版本的编译器可以自由使用完全不同的调用约定,这会在编译器没有警告的情况下与您的代码混淆。

请参阅: http: //www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2
请参阅本节末尾的注释

注意:静态成员函数不需要调用实际对象,因此指向静态成员函数的指针通常与常规指向函数的指针类型兼容。然而,尽管它可能适用于大多数编译器,但它实际上必须是一个 extern "C" 非成员函数才能正确,因为 "C 链接" 不仅包括名称修饰之类的东西,还包括调用约定,这C 和 C++ 之间可能有所不同。

编辑:
回答萨沙的评论:

以线程为例:

#include <iostream>
class Thread
{    public:   virtual void run()  = 0; };

extern "C" void* startThrerad(void* data)
{
    Thread*  thread = reinterpret_cast<Thread*>(data);
    try
    {
        thread->run();
    }
    catch(...)
    {    /* Log if required. Don't let thread exit with exception. */ }
    return NULL;
}
class MyJob: public Thread
{
    public: virtual void run() {std::cout << "HI\n";}
};
int main()
{
    MyJob     job; // MyJob inherits from Thread
    pthread_t th;

    // In most situation you do not need to dynamic cast.
    // But if you use multiple inheritance then things may get
    // interesting, as such best to always use it.
    pthread_create(&th,NULL,startThrerad,dynamic_cast<Thread*>(&job));

    void*     result;
    pthread_join(th,&result);
}
于 2009-06-09T22:55:57.240 回答
-1

我对 Windows thead 程序和其他各种回调执行等效操作,并且 RTX 一直中断。唯一真正的问题是成员必须是静态的(您已经知道了),并且您必须确保您的例程设置为使用标准的 C/系统调用调用约定。可悲的是,你如何做到这一点取决于平台。在 Win32 中,它带有“__stdcall”修饰符。

请注意,您可以使用回传指针参数将此类调用“转换”为普通的类方法调用。像这样(“self_calling_callback”是静态方法):

unsigned long __stdcall basic_thread::self_calling_callback (void *parameter) {
   if (parameter) {
      basic_thread * thread = reinterpret_cast<basic_thread *>(parameter);
      thread->action_callback();
   }
   return 0; 
   // The value returned only matters if someone starts calling GetExitCodeThread
   // to retrieve it.
}

basic_thread::basic_thread () {
   // Start thread.
   m_Handle = CreateThread(NULL,
                           0,
                           self_calling_callback,
                           (PVOID)this,
                           0,
                           &m_ThreadId );
   if( !IsHandleValid() )
      throw StartException("CreateThread() failed", GetLastError());
}
于 2009-06-09T18:34:10.247 回答
-1

那应该工作得很好。事实上,您可以扩展该函数以根据捕获的信号调用该类的特定实例。例如,如果您向您的类添加一个非静态方法 Process,您可以执行以下操作:

SignalProcessor* sp[MAX_SIGNALS];

static void SignalProcessor::OnMySignal(int sig_num)
{
      printf("Caught %d signal\n", sig_num);

      if (0 < sp[sig_num])
            sp[sig_num]->Process();

      fflush(stdout);

      return;

}
于 2009-06-09T18:40:30.763 回答