我有以下问题。我有一个来自外部库(无法修改)的函数,如下所示:
void externalFunction(int n, void udf(double*) );
我想将udf函数作为现有类的函数成员传递。请查看以下代码:
// External function (tipically from an external library)
void externalFunction(int n, void udf(double*) )
{
// do something
}
// User Defined Function (UDF)
void myUDF(double* a)
{
// do something
}
// Class containing the User Defined Function (UDF)
class myClass
{
public:
void classUDF(double* a)
{
// do something...
};
};
int main()
{
int n=1;
// The UDF to be supplied is myUDF
externalFunction(n, myUDF);
// The UDF is the classUDF member function of a myClass object
myClass myClassObj;
externalFunction(n, myClassObj.classUDF); // ERROR!!
}
我不能将classUDF成员函数声明为静态函数,因此上面代码的最后一行会导致编译错误!
答案 0 :(得分:6)
这是不可能的 - 在c ++中,你必须使用自由函数或静态成员函数,或者(在c ++ 11中)没有捕获的lambda来获取函数指针。
GCC允许你创建嵌套函数,它可以做你想要的,但只能在C中。它使用所谓的trampolines来做到这一点(基本上是一小块动态生成的代码)。可以使用此功能,但前提是您将一些调用externalFunction
的代码拆分为单独的C模块。
另一种可能性是在运行时生成代码,例如。使用libjit。
因此,如果你对非重入函数没问题,请创建一个全局/静态变量,该变量将指向this
并在静态函数中使用它。
class myClass
{
public:
static myClass* callback_this;
static void classUDF(double* a)
{
callback_this.realUDF(a);
};
};
它真的很可怕的代码,但我担心你的externalFunction
这样糟糕的设计会让你失望。
答案 1 :(得分:5)
您可以使用Boost绑定或TR1绑定(在最近的编译器上);;
<击> 撞击>
<击>externalFunction(n, boost::bind(&myClass::classUDF, boost::ref(myClassObj)));
击> <击> 撞击>
不幸的是,在过去的10分钟里我一直梦想着。前进的唯一方法是使用某种静态包装函数调用目标。其他答案有各种简洁(特定于编译器)的花絮,但这里是主要技巧:
void externalFunction(int n, void (*udf)(double*) )
{ double x; udf(&x); }
myClass myClassObj;
void wrapper(double* d) { myClassObj.classUDF(d); }
int main()
{
externalFunction(1, &wrapper);
}
将绑定函数存储在如下变量中:
std::function<void(double*)> stored = std::bind(&myClass::classUDF, boost::ref(myClassObj))
(假设编译器现在支持C ++ 0x。我确定Boost在某处有一个boost :: function&lt;&gt;)
没有这样的魔法,你需要指向成员函数的指针语法:
编辑以向评论者澄清,显然这仅适用于 iff 您可以控制externalFunction的定义。这是对OP中的/ broken / snippet int的直接响应。
struct myClass
{
void classUDF(double* a) { };
};
void externalFunction(int n, void (myClass::*udf)(double*) )
{
myClass myClassObj;
double x;
(myClassObj.*udf)(&x);
}
int main()
{
externalFunction(1, &myClass::classUDF);
}
// mem_fun_ref example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
int main ()
{
std::vector<std::string> numbers;
// populate vector:
numbers.push_back("one");
numbers.push_back("two");
numbers.push_back("three");
numbers.push_back("four");
numbers.push_back("five");
std::vector <int> lengths (numbers.size());
std::transform (numbers.begin(), numbers.end(), lengths.begin(),
std::mem_fun_ref(&std::string::length));
for (int i=0; i<5; i++) {
std::cout << numbers[i] << " has " << lengths[i] << " letters.\n";
}
return 0;
}
答案 2 :(得分:2)
当我的MyClass是单身时,我就是这样做的:
void externalFunction(int n, void udf(double) );
class MyClass
{
public:
static MyClass* m_this;
MyClass(){ m_this = this; }
static void mycallback(double* x){ m_this->myrealcallback(x); }
void myrealcallback(double* x);
}
int main()
{
MyClass myClass;
externalFunction(0, MyClass::mycallback);
}