簡體   English   中英

C void *函數指針參數

[英]C void* function pointer argument

我正在嘗試在ARM中創建任務隊列。 基本思想如下。

typedef void (*funcpointer)(void *);     // the argument being passed will be a void pointer that I can hopefully typecast

struct sQueue{
   funcpointer       func_address;        // this stores the address of the function to be called
   void              *func_parameter;                   // this stores the address of the struct that is passed to the function
   uint32_t          TimeStamp;                  // the time at which the function should be called     
};

sQueue Func_List[10];

計划是要把應該調用的函數的地址放在Func_List [x] .func_address中。

我希望能夠將接受指向不同結構類型的指針的函數的地址放入func_address中。 這是一個例子:

void Config_ADC(sADC_Settings *pSettings);

void Enable_RX(sRX_Top_Settings *pSettings);

這兩個函數都有效地接受指向結構的32位指針,但是在這些情況下,這些結構具有不同的類型。

當我嘗試分配Func_List [x] .func_address = Config_ADC時,編譯器抱怨:

類型“ void(*)(sADC_Settings *)”的值不能分配給“ funcpointer”類型的實體

關於如何實現此目標的任何想法? 我當然可以將函數Config_ADC更改為接受void *指針,然后在函數內部進行類型轉換,但是我並不是真的想要這樣做。

IIRC通過具有不同簽名的函數指針來調用函數是UB。

對於每種不匹配的函數類型,您將需要一個代理函數。

void Config_ADC(sADC_Settings *pSettings);
void Config_ADC_proxy(void *pSettings){
  Config_ADC((sADC_Settings*) pSettings);
}

一種解決方案是將void指針轉換為函數內部:

void Config_ADC(void *p)
{
    sADC_Settings *pSettings = (sADC_Settings *)p;

(實際上,我不喜歡這樣,因為它不必要地占用了另一個變量,但是,我認為它已經比涉及棧管理和調用管理開銷的代理函數更好。當涉及到void *時,編譯器不應理會;然后在那里完全沒有開銷。)

您的特定ABI規范(特定於目標處理器,操作系統,甚至可能是編譯器)規定了如何調用C函數以及使用哪種調用約定 注意,某些形式的參數可能會通過某些硬件寄存器傳遞。

我建議使用typedef -s定義稱為指針的函數的任何簽名:

typedef void myroutofint_t(int);
typedef int  myintof2int_t (int, int);

如果確定被調用函數的簽名並且可以通過指針列出被調用函數的所有簽名,則可以使用未修飾的並集(在C99或C11中):

struct sQueue{
 enum functiontype_en funtype;
 union {
   void* funaddress;
   myroutofint_t *funroutofint;
   myintof2int_t *funintof2int;
 };
 // othe fields of SQueue
 };

C標准甚至不需要功能指針和數據指針位於相同的地址空間中並且具有相同的大小。 但是POSIX會這樣做,我們假設是這樣。

順便說一句,您可能需要libffi

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM