[英]Function with same names in different files - C
我有兩個同名的函數,想在我的應用程序中使用它。
我在這里和這里提到了各種答案,但無法得到明確的解決方案。
我有以下功能
// xxxx_input.h
int8_t input_system_init(InputParams params);
int8_t input_system_easy_load(uint32_t interval_ms);
// yyyy_input.h
int8_t input_system_init(InputParams params);
int8_t input_system_easy_load(uint32_t interval_ms);
有兩個文件的原因是xxxx_input
和yyyy_input
內部工作方式不同。
修改 function 並不容易,因為代碼是由外部提供的,我們必須保留 xxxx_input 文件。
我們可以做的是修改yyyy_input.h
但像input_system_easy_load
這樣的函數要保持一致,因為它們是從不同的地方調用的。
有沒有辦法我們可以達到同樣的效果?
我嘗試用xxxx_input
替換yyyy_input.h
但由於包含目錄已經包含相同的 function 它給出了錯誤。
input_system_init 多次定義(由 xxxx_input.o 和 yyyy_input.o)。
如果您有xxxx_input.h
和yyyy_input.h
中定義的函數的源代碼,則可以使用命令行選項編譯這兩個模塊,通過預處理器重新定義 function 名稱:
gcc -Dinput_system_init=xxxx_input_system_init -Dinput_system_easy_load=xxxx_input_system_easy_load xxxx_input.c
gcc -Dinput_system_init=yyyy_input_system_init -Dinput_system_easy_load=yyyy_input_system_easy_load yyyy_input.c
然后,您將使用修改后的原型編譯您的代碼,您可以將所有 3 個模塊鏈接在一起。
如果模塊僅以 object 形式提供,您可以定義包裝函數xxxx_input_system_init
和xxxx_input_system_easy_load
,您將與 xxxx_input.o 鏈接以生成動態庫,對於yyyy
替代方案也是如此。 您將在模塊中使用修改后的原型,並將其與動態庫鏈接。
Mike Kinghan 在objcopy
可用的系統上為 object 文件和庫展示了一種更簡單的方法。
要自動獲取修改后的原型,您可以使用此包含文件:
my_input_system.h :
#define input_system_init xxxx_input_system_init
#define input_system_easy_load xxxx_input_system_easy_load
#include "xxxx_input.h"
#undef input_system_init
#undef input_system_easy_load
#define input_system_init yyyy_input_system_init
#define input_system_easy_load yyyy_input_system_easy_load
#include "yyyy_input.h"
#undef input_system_init
#undef input_system_easy_load
/* prevent direct use of the redefined functions */
#define input_system_init do_not_use_input_system_init@
#define input_system_easy_load do_not_use_input_system_easy_load@
如果您的供應商為您提供了使用 GCC 或 Clang 編譯的用於 GNU/Linux 計算機的 object 文件,我將介紹您可以使用的解決方案。
我的供應商給了我一個 header foo_a.h
文件,該文件聲明了 function foo
$cat foo_a.h
#pragma once
extern void foo(void);
和匹配的 object 文件foo.o
:
$ nm foo_a.o
0000000000000000 T foo
U _GLOBAL_OFFSET_TABLE_
U puts
定義foo
。
同樣,他們給了我一個 header foo_b.h
也聲明了foo
$ cat foo_b.h
#pragma once
extern void foo(void);
和匹配的 object 文件foo_b.o
$ nm foo_b.o
0000000000000000 T foo
U _GLOBAL_OFFSET_TABLE_
U puts
這也定義了foo
。
函數foo_a.o:foo
和foo_b.o:foo
做不同的事情(或同一件事的不同變體)。 我想在同一個程序prog.c
中做這兩件事:
$ cat prog.c
extern void foo_a(void);
extern void foo_b(void);
int main(void)
{
foo_a(); // Calls `foo_a.o:foo`
foo_b(); // Calls `foo_b.o:foo`
return 0;
}
我可以制作如下這樣的程序:
$ objcopy --redefine-sym foo=foo_a foo_a.o prog_foo_a.o
$ objcopy --redefine-sym foo=foo_b foo_b.o prog_foo_b.o
現在我制作了prog_foo_a.o
的foo_a.o
的副本,其中符號foo
重命名為foo_a
,以及prog_foo_b.o
的foo_b.o
的副本,其中符號foo
重命名為foo_b
。
然后我像這樣編譯和鏈接:
$ gcc -c -Wall -Wextra prog.c
$ gcc -o prog prog.o prog_foo_a.o prog_foo_b.o
prog
運行如下:
$ ./prog
foo_a
foo_b
也許我的供應商在 static 庫liba.a
中給了我foo_a.o
,該庫還包含其他 object 文件,這些文件引用foo_a.o:foo
? 與foo_b.o
類似。
沒關系。 代替:
$ objcopy --redefine-sym foo=foo_a foo_a.o prog_foo_a.o
$ objcopy --redefine-sym foo=foo_b foo_b.o prog_foo_b.o
我會跑:
$ objcopy --redefine-sym foo=foo_a liba.a libprog_a.a
$ objcopy --redefine-sym foo=foo_b libb.a libprog_b.a
這將為我提供一個新的 static 庫libprog_a.a
,其中foo
在庫中的所有 object 文件中重命名為foo_a
。 同樣, foo
在整個libprog_b.a
foo_b
然后我將鏈接prog
:
$ gcc -o prog prog.o -L. -lprog_a -lprog_b
考慮此解決方案的潛在缺點。 可能我的供應商給了我帶有調試信息的foo_a.o
和foo_b.o
,我想用它來調試我的prog
gdb
我已將原始符號名稱foo_a.o:foo
更改為foo_a
並將foo_b.o:foo
更改為foo_b
,但我沒有更改與這些符號相關的調試信息。 使用gdb
進行調試仍然可以工作,但某些調試 output 會不正確並且可能會造成混淆。 例如,如果我在foo_a
上設置斷點, gdb
將運行到它並停止,但它會說它已在文件foo
中foo_a.c
。 如果我在foo_b
斷點, gdb
將運行到它並再次說它在foo
,但來自文件foo_b.c
。 如果進行調試的人不知道程序是如何構建的,那肯定會令人困惑。
但是用二進制文件給你調試信息與給你源代碼不遠,所以你沒有源代碼,你可能沒有調試信息並且不關心它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.