Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将指向成员函数的指针传递给C函数?_C++_C_Function Pointers_Winpcap_Calling Convention - Fatal编程技术网

C++ 如何将指向成员函数的指针传递给C函数?

C++ 如何将指向成员函数的指针传递给C函数?,c++,c,function-pointers,winpcap,calling-convention,C++,C,Function Pointers,Winpcap,Calling Convention,可能重复: 我正在使用C库(winpcap)编写一个面向对象的库。我需要传递当网络数据包作为函数指针到达时调用的回调函数。我想传递一个成员函数指针到winpcap,以保持我的设计面向对象,并允许不同的对象接收不同的数据包。然而,据我所知,成员函数具有不同的调用约定,因此不能传递给C函数。有没有办法解决这个问题。我对boost::bind的实验(除了尝试和错误之外,我几乎无法使用它)没有什么成果 有没有办法改变成员函数的调用约定 这是我现在使用的回调函数的定义,以及它实际传递给winpcap的过

可能重复:

我正在使用C库(winpcap)编写一个面向对象的库。我需要传递当网络数据包作为函数指针到达时调用的回调函数。我想传递一个成员函数指针到winpcap,以保持我的设计面向对象,并允许不同的对象接收不同的数据包。然而,据我所知,成员函数具有不同的调用约定,因此不能传递给C函数。有没有办法解决这个问题。我对boost::bind的实验(除了尝试和错误之外,我几乎无法使用它)没有什么成果

有没有办法改变成员函数的调用约定

这是我现在使用的回调函数的定义,以及它实际传递给winpcap的过程

void pcapCallback( byte* param, const struct pcap_pkthdr* header, const byte* pkt_data );

pcap_loop( adhandle, 0, pcapCallback, NULL );
pcap_循环只取函数名(目前在全局范围内)。这是函数指针参数(的第三个参数)的定义。因为这是第三方代码,所以我不能真正更改它。我必须有一个成员函数,可以采用以下形式:

typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *);

据我所知,成员函数将使用此调用,而c函数指针需要一个cdecl

您只能将
静态
成员函数传递给c API。

如果您想让c API调用成员函数,您必须传递两条数据:静态成员函数及其要调用的对象

通常,C API回调具有某种形式的“用户数据”,通常是一个
void*
,您可以通过它来隧道对象的地址:

// Beware, brain-compiled code ahead!

typedef void (*callback)(int data, void* user_data);

void f(callback cb, void* user_data);

class cpp_callback {
public:
  virtual ~cpp_callback() {} // sometimes needed
  void cb(int data) = 0;
  callback* get_callback() const {return &cb_;}
private
  static void cb_(int data, void* user_data)
  {
    cpp_callback* that = reinterpret_cast<my_cpp_callback*>(user_Data);
    that->cb(data);
  }
};

class my_callback {
public:
  void cb(int data) 
  {
     // deal with data
  }
};

void g()
{
  my_callback cb;
  f(cb.get_callback(), &cb);
}

与全局数据一样,如果回调的多个实例处于活动状态,则这是危险的。我试着把伤害降到最低,这样如果它们的生命是嵌套的,它就会起作用。不过,其他任何事情都会造成伤害

请参考关于

<强>如何实现静态C++成员函数的回调?<强> < /P>

<强>如何实现对非静态C++成员函数的回调?<强> < /P>


和的副本。谢谢,我没有找到那个。好吧,这是不正确的,请参阅其他答案和重复问题的答案。解决这个问题有很多方法,这些方法正是我想要的。@ufotds:虽然确实可以使用巧妙的技巧使
静态
成员函数调用非
静态
成员函数,但也确实只能将(指向)
静态
成员函数的指针传递给C API。所以Paul确实是对的,虽然这比他写的要多。好的,显然我问题的标题应该提到一个非静态成员函数。。。在这方面,静态函数与调用成员函数的全局函数一样好(稍微好一点)。当你处理像glutDisplayFunc这样的函数时,这会很痛苦,它的回调函数是void(u cdecl*)(void);因此,display进程无法知道是谁调用了它,而不会不可避免地造成竞争条件或要求使用锁(因为如果不将调用方存储在全局状态,或者不使用全局状态将函数的地址映射到它的前一个调用方,就无法让不同的回调确定调用它们的人,但这样做意味着更改此映射可能会导致数据争用)@Dimitry:如果C API回调没有提供用户提供的参数,那么它要么不打算与某些特定数据块结合使用,要么API创建者很笨。不管怎样,你都需要编写一个自由函数。是的,但是不管怎样,当用户想在glut之上编写库时,他们将无法让display被使用意识到他们的场景图没有一个本地的,或者未来可能的比赛。
// Beware, brain-compiled code ahead!

typedef void (*callback)(int data);

void f(callback cb);

class cpp_callback {
public:
  cpp_callback() : the_old_cb_(this) {std::swap(the_cb_,the_old_cb_);}
  virtual ~cpp_callback()            {std::swap(the_cb_,the_old_cb_);}
  void cb(int data) = 0;
  callback* get_callback() const {return &cb_;}
private
  static cpp_callback* the_cb_;
  cpp_callback* the_old_cb_;
  static void cb_(int data, void* user_data) 
  {
    the_cb_->cb(data);
  }
};

class my_callback {
public:
  void cb(int data) { /* deal with data */ }
};

void g()
{
  my_callback cb;
  f(cb.get_callback(), &cb);
}