我在 SWIG 中使用 lukes 答案,因为 SWIG 不支持所有 C++11 功能......这可能可以通过 Parsa Jamshidis 方法进一步改进。
我对其进行了修改以涵盖更多情况(可变数量的参数和可变返回类型):
#include <iostream>
template <typename R, typename ...T>
class Callback
{
public:
virtual ~Callback() {}
virtual R operator() (T... args) = 0;
};
template <typename R, typename ...T>
class FreeCallback : public Callback<R, T...>
{
public:
FreeCallback(R(*func)(T...)) : func_(func) {}
virtual R operator() (T... args) { return (*func_)(args...); }
private:
R(*func_)(T...);
};
template <typename tClass, typename R, typename ...T>
class MemberCallback : public Callback<R, T...>
{
public:
MemberCallback(tClass* instance, R (tClass::*memberfunction)(T...)) : instance_(instance), memberfunc_(memberfunction) {}
virtual R operator() (T... args) { return (instance_->*memberfunc_)(args...); }
private:
tClass * instance_;
R (tClass::*memberfunc_)(T...);
};
class foo {
public:
Callback<int, int> *IntCallback;
Callback<int, int, double, double> *IntDoubleDoubleCallback;
};
class blub {
public:
int func1(int i) {
std::cout << "args: " << i << std::endl;
return 1;
}
int func2(int i, double d1, double d2){
std::cout << "args: " << i << " " << d1 << " " << d2 << std::endl;
return 0;
}
};
int freeFunc1(int i) {
std::cout << "args: " << i << std::endl;
return 1;
}
int freeFunc2(int i, double d1, double d2){
std::cout << "args: " << i << " " << d1 << " " << d2 << std::endl;
return 0;
}
int main() {
foo f;
blub b;
f.IntCallback = new MemberCallback<blub, int, int>(&b, &blub::func1);
f.IntDoubleDoubleCallback = new MemberCallback<blub, int, int, double, double>(&b, &blub::func2);
Callback<int, int> *IntFreeCallback = new FreeCallback<int, int>(&freeFunc1);
Callback<int, int, double, double> *IntDoubleDoubleFreeCallback = new FreeCallback<int, int, double, double>(&freeFunc2);
int ret = (*IntFreeCallback)(42);
std::cout << "ret freeFunc1: " << ret << std::endl;
ret = (*IntDoubleDoubleFreeCallback)(42, 3.1415, 2.7182);
std::cout << "ret freeFunc2: " << ret << std::endl;
ret = (*f.IntCallback)(42);
std::cout << "ret func1: " << ret << std::endl;
ret = (*f.IntDoubleDoubleCallback)(42, 3.1415, 2.7182);
std::cout << "ret func2: " << ret << std::endl;
std::cout << "Hello World!\n";
// cleanup not done here...
}