簡體   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