就鏈接器而言,沒有特別的要求,並且不需要考慮弱的混疊。
基本規則是:只要用戶代碼沒有引用鏈接到庫中的給定.c
或.s
文件中的任何符號,該文件的內容就不會在可執行文件中結束。
在您描述的場景中,您的函數可能永遠不會成爲死代碼,因爲您的「實時」代碼可能引用其地址來設置默認函數指針值。爲了確保不會發生,你必須做到以下幾點:
只有從用戶可調用可選default_init
功能中,請參閱更換功能。
的default_init
決不能在你的代碼的任何地方調用,沒有任何必須的功能,在任何地方,但內default_init
引用。
將可替換的函數和init函數放入至少一個.c
或彙編文件中,該文件不用於任何其他代碼。
爲用戶更換所有的功能,他們只需要從不調用default_init
功能。如果你想功能可更換一個接一個,你必須去,另外:
在其自己的.c
文件中的每個替換功能。
讓用戶不要直接調用default_init
,而是將所需的默認或用戶提供的實現傳遞給您的init
函數。
你在做什麼,實際上,不是「覆蓋」的任何實現,但根本就沒有使用它。
例(包括省略清晰後衛):
// api.h
void api_fun1(void);
void api_fun2(void);
void api_default_init(void);
void api_user_init(void (*f1)(void), void (*f2)(void));
void api_use_funs(void);
// api_internal.h
extern void (*api_f1)(void);
extern void (*api_f2)(void);
// common.c
#include "api.h"
#include "api_internal.h"
void (*api_f1)(void);
void (*api_f2)(void);
void api_user_init(void (*f1)(void), void (*f2)(void)) {
api_f1 = f1;
api_f2 = f2;
}
void api_use_funs(void) {
api_f1();
api_f2();
}
// api_fun1.c
#include "api.h"
void api_fun1(void) {}
// api_fun2.c
#include "api.h"
void api_fun2(void) {}
// api_default_init.c
#include "api.h"
#include "api_internal.h"
void api_default_init(void) {
api_f1 = api_fun1;
api_f2 = api_fun2;
}
比方說,用戶要覆蓋api_fun2
自己:
// main.c
#include "api.h"
#include <stdio.h>
void my_fun2() {
printf("%s\n", __FUNCTION__);
}
int main() {
api_user_init(api_fun1, my_fun2);
api_use_funs();
}
也許看看[弱混疊(HTTP:/ /stackoverflow.com/questions/15525537/what-are-practical-applications-of-weak-linking)。 – Downvoter
弱主要是由主要編譯器供應商(即MSVC,gcc,鐺,Intel C ...)支持的東西 – MarkP
絕對GCC,其他可能也是如此。 – Downvoter