如何将指向非静态成员方法的指针传递给 extern "C" 函数?
How do I hand over a pointer to a non-static member method to an extern "C" function?
我有一个名为 tmc 的 class,它现在包含(除其他外,此处不相关)一个私有构造函数,一个静态工厂方法,以及一个名为 ReadLoop (void*)
:
的实例方法
extern "C" {
#include <pigpiod_if2.h>
}
class tmc {
public:
static tmc* Initialize ();
static int main ();
private:
void *ReadLoop (void *params);
tmc ();
pthread_t *tmc_receiver_reader;
};
tmc::tmc ()
: tmc_receiver_reader (start_thread (tmc::ReadLoop, NULL))
{
}
void* tmc::ReadLoop (void *params)
{
return params;
}
tmc* tmc::Initialize ()
{
tmc* instance = new tmc ();
return instance;
}
int tmc::main ()
{
return (tmc::Initialize ()) == NULL ? 0 : 1;
}
现在的问题是:如何使用ReadLoop
作为函数指针与pigpiod_if2
中包含的start_thread ()
函数一起使用?由于以下错误,此处显示的代码无法编译:
error: invalid use of non-static member function ‘void* tmc::ReadLoop(void*)’
tmc_receiver_reader (start_thread (tmc::ReadLoop, NULL))
我在 SO 上看到了几个问题,它们的错误消息相同,但其中 none 是关于指向 C 函数的非静态成员方法的指针。请注意,即使这里创建的对象是单例,我也无法将 ReadLoop ()
设为静态。我在 Raspbian Buster 上使用 g++ 6.5.0。谢谢。
幸运的是,C 接口提供了一个 void*
回传来帮助解决这个问题。您可以使用它来指向正确的 tmc
对象:
extern "C" void* tmc_pigpio_ReadLoop_callback(void* userdata);
class tmc {
// ...
private:
void* ReadLoop();
friend void* tmc_pigpio_ReadLoop_callback(void*);
// ...
};
void* tmc_pigpio_ReadLoop_callback(void* userdata)
{
auto* tmcp = static_cast<tmc*>(userdata);
return tmcp->ReadLoop();
}
// Note "this" passed to start_thread.
tmc::tmc ()
: tmc_receiver_reader (start_thread (tmc_pigpio_ReadLoop_callback, this))
{
}
或者,如果您已经将 void* userdata
用于不同的用途,请将 tmc*
指针添加到它指向的结构,或者创建一个包含 tmc*
指针的新结构和要传递的其他数据。
根本无法在需要独立函数的地方使用 非静态 class 方法。它们不兼容。
您将不得不使用 static 或 non-member 代理函数。幸运的是,start_thread()
允许您将用户定义的参数传递给函数,因此您可以使用它来传递 tmc
实例的 this
指针,例如:
class tmc {
...
private:
static void* ReadLoopProxy(void *params);
void* ReadLoop();
tmc ();
pthread_t *tmc_receiver_reader;
};
tmc::tmc ()
: tmc_receiver_reader (start_thread (tmc::ReadLoopProxy, this))
{
}
void* tmc::ReadLoopProxy(void *params)
{
return static_cast<tmc*>(params)->ReadLoop();
}
void* tmc::ReadLoop()
{
return NULL;
}
...
我有一个名为 tmc 的 class,它现在包含(除其他外,此处不相关)一个私有构造函数,一个静态工厂方法,以及一个名为 ReadLoop (void*)
:
extern "C" {
#include <pigpiod_if2.h>
}
class tmc {
public:
static tmc* Initialize ();
static int main ();
private:
void *ReadLoop (void *params);
tmc ();
pthread_t *tmc_receiver_reader;
};
tmc::tmc ()
: tmc_receiver_reader (start_thread (tmc::ReadLoop, NULL))
{
}
void* tmc::ReadLoop (void *params)
{
return params;
}
tmc* tmc::Initialize ()
{
tmc* instance = new tmc ();
return instance;
}
int tmc::main ()
{
return (tmc::Initialize ()) == NULL ? 0 : 1;
}
现在的问题是:如何使用ReadLoop
作为函数指针与pigpiod_if2
中包含的start_thread ()
函数一起使用?由于以下错误,此处显示的代码无法编译:
error: invalid use of non-static member function ‘void* tmc::ReadLoop(void*)’
tmc_receiver_reader (start_thread (tmc::ReadLoop, NULL))
我在 SO 上看到了几个问题,它们的错误消息相同,但其中 none 是关于指向 C 函数的非静态成员方法的指针。请注意,即使这里创建的对象是单例,我也无法将 ReadLoop ()
设为静态。我在 Raspbian Buster 上使用 g++ 6.5.0。谢谢。
幸运的是,C 接口提供了一个 void*
回传来帮助解决这个问题。您可以使用它来指向正确的 tmc
对象:
extern "C" void* tmc_pigpio_ReadLoop_callback(void* userdata);
class tmc {
// ...
private:
void* ReadLoop();
friend void* tmc_pigpio_ReadLoop_callback(void*);
// ...
};
void* tmc_pigpio_ReadLoop_callback(void* userdata)
{
auto* tmcp = static_cast<tmc*>(userdata);
return tmcp->ReadLoop();
}
// Note "this" passed to start_thread.
tmc::tmc ()
: tmc_receiver_reader (start_thread (tmc_pigpio_ReadLoop_callback, this))
{
}
或者,如果您已经将 void* userdata
用于不同的用途,请将 tmc*
指针添加到它指向的结构,或者创建一个包含 tmc*
指针的新结构和要传递的其他数据。
根本无法在需要独立函数的地方使用 非静态 class 方法。它们不兼容。
您将不得不使用 static 或 non-member 代理函数。幸运的是,start_thread()
允许您将用户定义的参数传递给函数,因此您可以使用它来传递 tmc
实例的 this
指针,例如:
class tmc {
...
private:
static void* ReadLoopProxy(void *params);
void* ReadLoop();
tmc ();
pthread_t *tmc_receiver_reader;
};
tmc::tmc ()
: tmc_receiver_reader (start_thread (tmc::ReadLoopProxy, this))
{
}
void* tmc::ReadLoopProxy(void *params)
{
return static_cast<tmc*>(params)->ReadLoop();
}
void* tmc::ReadLoop()
{
return NULL;
}
...