繁体   English   中英

如何在C ++中传递通用函数指针?

[英]How can I pass generic function pointer in c++?

我要完成的工作是在嵌入式环境中注册回调。 该回调将采用以下两种形式之一:

void (*cb) (void *ctxt); or
void ClassA::VirtualFn (void);

该代码只能在使用GCC的ARM平台上运行。 由于在运行时完成了一些动态绑定,因此注册回调函数必须是虚拟的。 以上两个函数在汇编级别都是等效的(它们都使用一个指针)。 此外,出于性能目的,回调机制处于汇编状态,因为它发生在ISR上下文中,因此我不必为此担心。 我真正需要的是一个采用以上任何一种并存储传递的函数指针和上下文指针的函数。 即:

void isr_cb (void *ctxt) {}
gpio->RegisterIsr (isr_cb, cptr);
gpio->RegisterIsr (&ClassA::IsrHandler, this);

and indeed everything works as expected (apart from the compiler warnings). 我已经通过将虚拟成员函数强制转换为 ,实际上一切工作都按预期进行(除了编译器警告)。

virtual成员函数强制转换为void (*)(void *)听起来很苛刻。

你说:

由于在运行时完成了一些动态绑定,因此注册回调函数必须是虚拟的。

我认为这意味着您具有ClassA类型的对象。 如果正确,那么您应该:

  1. ClassAstatic成员注册到其签名为的回调机制中:

     void (*)(ClassA& ref); 
  2. 添加执行实际工作的virtual成员函数。

     void doStuff(); 
  3. 假设已注册的回调函数为:

     static void foo(Class& ref); 

    foo的实现中,对ref调用doStuff

     static void foo(Class& ref) { ref.doStuff(); } 

如果您可以利用c ++ 11中的std::bindboost::bind ,则将拥有更加轻松的时间。 如果接口(即实际输出类型和实际输入参数类型相同),则两者都可以让您将成员函数指针和自由函数彼此混合使用,例如

int f(double val)
{

}

class A {

   int memberf(double val);

}

A instanceOfA;
auto f1 = std::bind(f, std::placeholders::_1);
auto f2 = std::bind(&A::memberf, &instanceOfA, std::placeholders::_1);

现在, f1f2都是带double并返回int函数,而与以下事实无关:一个是成员函数,另一个是自由函数,因此不需要强制转换。 我不得不承认我不能从内存中写出实际的类型。

首先,在C和C ++中都没有通用的函数指针。

完全合格和高性能的解决方案仍然是可能的。

由于非成员函数已经是正确的类型,因此它是微不足道的。

  1. 如果您知道可能要传递的全套非虚拟成员功能和虚拟功能插槽,请为每个定义一个简单的转发器,方法如下:

     void forward_to_IsrHandler(void* p) { ((ClassA*)p)->IsrHandler(); } gpio->RegisterIsr (forward_to_IsrHandler, (void*)this); 
  2. 如果您不知道或真的想在性能方面牺牲标准一致性,则可以将成员函数指针转换为普通函数指针(gcc扩展,其他编译器也有自己的)

     void (*tmp)(ClassA*) = (void(*)(ClassA*))&ClassA::IsrHandler; 

    使用-Wno-pmf-conversions删除使用扩展名的警告。
    由于在ARM上对函数void(*)(void*)void(*)(ClassA*)的调用看起来完全相同,因此即使严格地说是UB,也可以使用它:

     gpio->RegisterIsr ((void(*)(void*))tmp, (void*)this); 

仅针对较小的代码段选择性地禁用GCC警告

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wno-pmf-conversions"
    // Do the foul deed here
#pragma GCC diagnostic pop

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM