簡體   English   中英

Function 在不同的文件中具有相同的名稱 - C

[英]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_inputyyyy_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.hyyyy_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_initxxxx_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:foofoo_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.ofoo_a.o的副本,其中符號foo重命名為foo_a ,以及prog_foo_b.ofoo_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.ofoo_b.o ,我想用它來調試我的prog gdb

我已將原始符號名稱foo_a.o:foo更改為foo_a並將foo_b.o:foo更改為foo_b ,但我沒有更改與這些符號相關的調試信息。 使用gdb進行調試仍然可以工作,但某些調試 output 會不正確並且可能會造成混淆。 例如,如果我在foo_a上設置斷點, gdb將運行到它並停止,但它會說它已在文件foofoo_a.c 如果我在foo_b斷點, gdb將運行到它並再次說它在foo ,但來自文件foo_b.c 如果進行調試的人不知道程序是如何構建的,那肯定會令人困惑。

但是用二進制文件給你調試信息與給你源代碼不遠,所以你沒有源代碼,你可能沒有調試信息並且不關心它。

暫無
暫無

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

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