2017-09-05 71 views
1

這是C中的一種獨特情況。覆蓋函數指針的實現並用於共享庫

說我們圖書館稱爲libfoo.solibbar.so,並在這兩個我們同樣的功能名稱,Get_A,假設Get_A由系統調用。

libbar被加載,然後用參數G調用它的Get_AG是一些函數指針一個結構,有感興趣的一個:

(*G)->RegisterBaz

所以libbar的調用Get_A,我們要變異的指針,RegisterBaz函數,然後調用libfoo'的S版Get_A藉助於dlopen + dlsym。

有一兩件事我想直接分配,但後來我的一個編譯器錯誤只讀變量無法分配的,所以我試圖去通過指針:

// not void * but actually some function signature typedefed. 
void *f_ptr = (*G)->RegisterBaz; 
*&f_ptr = r_n; 

r_n是一個普通的C函數具有相同簽名RegisterBaz

r_n我叫原來實行的RegisterBaz

因此,雖然這並不賽格故障,它不帶d打電話給我的包裝功能。

回答

2

所以,當你做了直接賦值,你可能試圖給const函數指針分配一個函數;這顯然不是你能做的事情。

此外,在代碼:

void *f_ptr = (*G)->RegisterBaz; 
*&f_ptr = r_n; 
實際上

f_ptr指向(*G)->RegisterBaz正指向同樣的事情,所以,當你改變f_ptr*&(基本無操作)你是不是完全沒有修改(*G)->RegisterBaz

另外,您不能將函數指針分配給對象指針; void *類型的東西只能保證能夠保存對象指針。 (INCITS-ISO-IEC 9899-2011 6.3.2.3p7

所以,如果出於某種原因,你死心塌地改變(*G)->RegisterBaz直接,你可以這樣做:

void (**f_ptr)(void) = (void (**)(void))&((*G)->RegisterBaz); 
*f_ptr = r_n; 

但因爲你將要通過(*G)->RegisterBaz調用,您需要確保替換函數簽名與(*G)->RegisterBaz碰巧指向的函數簽名相匹配。

除非f_ptr的類型爲指針指向"insert signature of called function here",否則您也會收到警告。

我需要重申這不是你通常想要做的事情,所以我不能保證這將起作用。但是,如果你死定了它,這是你將如何做到這一點(基本上你是const的const函數指針別名非const)

+0

嗯,這樣做給我一個seg故障。 –

+0

您是否100%確定您要替換的功能提供了所有相同的功能?你不能用你自己的庫來替換一個庫函數,只是因爲簽名匹配期望它是花哨的。 –

+0

簽名是正確的,什麼可能是錯誤的,我可以從哪裏開始尋找線索或尋找。 AFAIK我的事情是正確的。 –