如何从成员函数中获取“简单”函数指针

时间:2013-04-11 20:45:56

标签: c++ type-conversion function-pointers member c++builder-xe

我遇到了函数指针的问题,我在网上找不到任何东西帮我解决了这个问题。

我有一个来自C API的函数,它接受一个void函数的指针:

extern int APIFunction(int, void (*func)(int));

当我调用API函数时,我有一个具有我想要的函数的类。

class MyClass
{
   public:
      void myFunction(int status, otherAPi arguments...);
};

然后,我创建了一个指向我的成员函数的指针,并创建了一个新类的实例

typedef  void (MyClass::*MyClassFunctionPointer)(int stat, otherAPi arguments...);
MyClassFunctionPointer fctPointer= &MyClass::myFunction; 
LicenseSecurity instance;  

当我尝试使用我创建的函数指针调用我的APi函数时出现错误:

int stat = APIFunction(5, fctPointer ); // -> error 1
int stat = APIFunction(5, instance.*fctPointer ); // -> error 2

我在第一种和第二种情况下分别遇到错误:

E2034 Impossible to convert 'void (MyClass::*)(int, otherAPITypes...)' into 'void (*) (int, otherAPITypes...)'
E2342 Bad type correspondence in the parameter 'func' ('void (*)(int, otherAPITypes...)' desired, 'void(int, otherAPITypes...)' obtained)

我无法访问API函数,因此无法对其进行修改。总结问题:如何获得一个“简单”的C函数指针,从我的类的成员函数中放入函数的参数?

由于

4 个答案:

答案 0 :(得分:2)

不幸的是,你做不到。遗憾。

理想情况下,您的API会接受类似std::function的内容,允许您自由包含函数或成员函数。但如果您无法修改API,那么您别无选择,只能提供免费功能。

答案 1 :(得分:0)

你无法获得简单的"函数指向非静态成员函数的函数,因为函数在调用时需要this指针。如果你要创建一个类似的函数指针,那么在调用函数时,就没有这个指针供它引用。

答案 2 :(得分:0)

使用这样的古老C API,遗憾的是你无法做到这一点。

您需要做的是创建一个静态或非成员函数来进行回调,然后找出要调用该成员的对象的哪个实例。某些C API允许将用户数据传递给回调,在这种情况下,您可以使用它来存储有问题的this指针。如果那不是一个选项,你可以使用全局或单例对象,只允许注册一个这样的回调。

答案 3 :(得分:0)

您可以将回调声明为独立函数或类的静态方法。棘手的部分是访问回调内的类实例指针。

理想情况下,精心设计的API允许您为回调指定用户定义的值。这允许您轻松传入类实例并直接在回调中访问它。但听起来你没有使用这样的API,所以你需要使用一种解决方法。

如果一次只有1个类实例与API一起使用,则可以将实例指针存储到全局变量中,并让回调使用全局变量来访问实例。

但是如果你同时使用多个类实例,那么你正在寻找一个类似于VCL的MakeObjectInstance()函数的thunking解决方案,它允许使用TWndMethod - 签名类方法作为Win32窗口过程回调。本质上,动态分配可执行存储器块,将存根汇编程序代码写入块,并且实例指针和类方法指针也存储在块中。然后将该块传递给API,就像它是一个函数指针一样。当API调用“函数”时,存根代码被执行,它必须操纵调用堆栈和CPU寄存器来调用存储的类方法指针,将存储的实例指针作为其隐藏的this参数传递,同时保留其他参数的语义,调用栈,函数结果等

C ++中的任何内容都无法真正实现这种类型的thunking。手动实现并不困难,但它也不是微不足道的(看看VCL的Classes.pas源文件中的MakeObjectInstance()的源代码)。最难的部分是提供必要的存根代码,该代码与特定类方法签名的语义相匹配。