重要的是要注意,除非你可以更改接收函数的代码签名,否则没有(简单的)方法来实现这一点。这将尝试在不具有与函数相同的闭包的语言中实现闭包(C++ 中闭包的签名不同)。
有两种实际的方法可以实现这一点:
1. 使用某种单例/全局变量来存储闭包,然后传递一个帮助函数,使用该闭包调用所需的函数。以下是一个示例:
2. 在需要闭包时创建一个新的可调用对象,并将其传递给需要它的代码。
#include <stdio.h>
template<class C, typename ReturnType, typename... Args>
class ClosureSingleton {
typedef ReturnType (C::*FuncType)(Args...);
public:
static ClosureSingleton& getInstance() {
static ClosureSingleton instance;
return instance;
}
void setClosure(C* obj, FuncType f) {
this->obj = obj;
this->function = f;
}
static ReturnType funcPtr(Args... args) {
C* obj = getInstance().obj;
auto func = getInstance().function;
return (obj->*func)(args...);
}
private:
ClosureSingleton() {}
C* obj;
FuncType function;
public:
ClosureSingleton(ClosureSingleton const&) = delete;
void operator=(ClosureSingleton const&) = delete;
};
class aClass {
public:
void aTest1(int a, int b) { printf("%d + %d = %d\n", a, b, a + b); }
int aTest2(int a, int b) { return a + b; }
};
void function1(void (*function)(int, int)) {
function(1, 1);
}
int function2(int (*function)(int, int)) {
return function(1, 1);
}
int main() {
aClass tmp;
ClosureSingleton<aClass, void, int, int>::getInstance().setClosure(
&tmp, &aClass::aTest1);
function1(&ClosureSingleton<aClass, void, int, int>::funcPtr);
ClosureSingleton<aClass, int, int, int>::getInstance().setClosure(
&tmp, &aClass::aTest2);
printf(
"function2: %d\n",
function2(&ClosureSingleton<aClass, int, int, int>::funcPtr));
return 0;
}
当然,这种方法的明显缺点是需要在每次调用之前设置闭包,并且存在一些线程安全问题。虽然不理想,但在特定情况下可能可行。
- 使用像asmjit或动态编译这样的东西来动态编译并传递函数到C代码中。这仅适用于允许将堆段标记为可执行的机器。由于要编写汇编代码来实现这一点,因此非常不可移植。但是,如果您使其工作,那么您确实会拥有真正的闭包,尽管与大多数编程语言实现闭包的方式相比,创建闭包的成本要高得多(它们不会重复函数组装体,而是使用上下文对象)。
- 修补具有函数处理程序的lib / dll以更改其签名以允许上下文对象。同样,这是一个非常脆弱和不优化的解决方案。
我的原始答案,它并没有真正回答问题,但人们发现它很有用:
不确定为什么这个极其简单的解决方案被忽略了:
#include <stdio.h>
class aClass
{
public:
void aTest(int a, int b)
{
printf("%d + %d = %d\n", a, b, a + b);
}
};
template<class C>
void function1(void (C::*function)(int, int), C& c)
{
(c.*function)(1, 1);
}
void function1(void (*function)(int, int)) {
function(1, 1);
}
void test(int a,int b)
{
printf("%d - %d = %d\n", a , b , a - b);
}
int main (int argc, const char* argv[])
{
aClass a;
function1(&test);
function1<aClass>(&aClass::aTest, a);
return 0;
}
输出:
1 - 1 = 0
1 + 1 = 2