使用C++类的成员函数为C回调函数
我有一个C库,需要一个回调函数被注册来定制一些处理。回调函数的类型是int a(int *, int *)
。使用C++类的成员函数为C回调函数
我写类似以下内容并尝试注册一个C++类的函数作为回调函数的C++代码:
class A {
public:
A();
~A();
int e(int *k, int *j);
};
A::A()
{
register_with_library(e)
}
int
A::e(int *k, int *e)
{
return 0;
}
A::~A()
{
}
编译器会引发以下错误:
In constructor 'A::A()',
error:
argument of type ‘int (A::)(int*, int*)’ does not match ‘int (*)(int*, int*)’.
我的问题:
- ,首先是有可能像我试图做注册一个C++类memeber功能,如果SO 3 H流? (我读32.8在http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html,但在我看来,这并没有解决问题)
- 是否有替代/更好的办法来解决呢?
你可以做,如果成员函数是静态的。
A类的非静态成员函数有一个隐含的class A*
类型的第一个参数,它对应于这个指针。这就是为什么只有在回调的签名具有class A*
类型的第一个参数时才能注册它们。
与使用成员函数的问题是,它需要在其上作用的对象 - 和C犯规知道对象。
最简单的方法是做到以下几点:
//In a header file:
extern "C" int e(int * k, int * e);
//In your implementation:
int e(int * k, int * e) { return 0; }
的问题是方法=功能!编译器将改变你的方法,这样的事情:
int e(A *this, int *k, int *j);
所以,它肯定不能传递它,因为类实例不能作为参数传递。解决问题的一种方法是将方法设置为静态,这样它就会具有良好的类型。但它不会有任何类实例,并且访问非静态类成员。
另一种方法是声明一个函数具有静态指向一个甲初始化的第一次。该功能只将呼叫重定向到该类别:
int callback(int *j, int *k)
{
static A *obj = new A();
a->(j, k);
}
然后您可以注册回调函数。
嗯......如果你是一个Win32平台上总有讨厌的置信转换方式...
Thunking in Win32: Simplifying callbacks to non-static member functions
这是一个解决方案,但我不建议使用它。
它有一个很好的解释,它很高兴知道它存在。
你也可以做到这一点,如果成员函数是不是静态的,但它需要多一点的工作(见Convert C++ function pointer to c function pointer):
#include <stdio.h>
#include <functional>
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
template <typename... Args>
static Ret callback(Args... args) {
func(args...);
}
static std::function<Ret(Params...)> func;
};
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;
void register_with_library(int (*func)(int *k, int *e)) {
int x = 0, y = 1;
int o = func(&x, &y);
printf("Value: %i\n", o);
}
class A {
public:
A();
~A();
int e(int *k, int *j);
};
typedef int (*callback_t)(int*,int*);
A::A() {
Callback<int(int*,int*)>::func = std::bind(&A::e, this, std::placeholders::_1, std::placeholders::_2);
callback_t func = static_cast<callback_t>(Callback<int(int*,int*)>::callback);
register_with_library(func);
}
int A::e(int *k, int *j) {
return *k - *j;
}
A::~A() { }
int main() {
A a;
}
这个例子是在这个意义上完整的,它编译:
g++ test.cpp -std=c++11 -o test
您将需要c++11
标志。在代码中,您看到调用了register_with_library(func)
,其中func
是一个动态绑定到成员函数e
的静态函数。
是的。该解决方案工作。 (A ::)(A *,int *,int *)'不匹配'int()(int,int *)' – Methos 2009-06-16 10:31:20
它确实存在,但是通过将(答::)这意味着函数是类A的一部分,它从那里暗示了'this'指针。 – GManNickG 2009-06-16 10:37:19
我只是好奇......这是在标准中指定的吗?我只是看了一下关于课程的部分,并没有发现这一点。尽管如此,非常有趣。我只是不会认为每个编译器都必须以这种方式处理非静态成员函数。 – Tom 2009-06-16 10:59:37