我正在对我的一个 cmets 进行一些扩展,以便正确格式化和描述这个想法。这在您的场景中可能不可行。
为了简化,我们有libx1,它公开了两个函数:libx_api 和libx1_api。此版本的库由 libx1_user 使用,它公开了一个 API:libx1_user,它同时使用了 libx1 API。
我们还有libx2,它公开了两个函数:libx_api 和libx2_api。
我们有一个程序 (prog),它依赖于 libx1_user 和 libx2。
我的建议是将libx2 包装在一个动态库libx2w 中,它公开了与libx2 相同的API,只是名称略有不同:w_libx_api 和w_libx2_api(仅具有共同的函数) libx1 和 libx2 之间的名称需要进行此更改,但我为这两个函数添加了 w_ 前缀以保持一致性。
现在,prog 的代码已更改,因此每个需要使用 API 的libx2 版本的地方都将实际使用libx2w 的包装器。这应该是一个易于自动化的更改。
代码示例(我将省略标题的内容,没有什么特别之处,只是函数原型):
libx1.c
#include <stdio.h>
#include "libx1.h"
void libx_api()
{
printf("In libx_api() from libx1\n");
}
void libx1_api()
{
printf("In libx1_api()\n");
}
libx2.c
#include <stdio.h>
#include "libx2.h"
void libx_api()
{
printf("In libx_api() from libx2\n");
}
void libx2_api()
{
printf("In libx2_api()\n");
}
libx1_user.c
#include <stdio.h>
#include "libx1_user.h"
#include "libx1.h"
void libx1_user()
{
printf("Entering libx1_user()\n");
libx_api();
libx1_api();
printf("Exiting libx1_user()\n");
}
libx2_wrapper.c
#include <stdio.h>
#include "libx2wrapper.h"
#include "libx2.h"
void w_libx_api()
{
libx_api();
}
void w_libx2_api()
{
libx2_api();
}
program.c
#include <stdio.h>
#include "libx1_user.h"
#include "libx2wrapper.h"
int main()
{
printf("Using libx1_user()\n");
libx1_user();
printf("Done!\n");
printf("Using libx2 wrappers\n");
w_libx_api(); // this was previously libx_api()
w_libx2_api(); // this was previously libx2_api()
printf("Done!\n");
return 0;
}
用于编译和链接的示例 CMakeLists.txt
我比 make 更熟悉 CMake,所以我发现编写相应的 CMakeLists.txt 而不是 Makefile 更容易。
project(prog)
add_library(x1 STATIC libx1.c)
add_library(x1_user STATIC libx1_user.c)
target_link_libraries(x1_user PRIVATE x1)
add_library(x2 STATIC libx2.c)
add_library(x2w SHARED libx2wrapper.c)
target_link_libraries(x2w PRIVATE x2)
add_executable(prog program.c)
target_link_libraries(prog PRIVATE x2w x1_user)
运行生成的程序
$ ./prog
Using libx1_user()
Entering libx1_user()
In libx_api() from libx1
In libx1_api()
Exiting libx1_user()
Done!
Using libx2 wrappers
In libx_api() from libx1
In libx2_api()
Done!
纳米输出
$ nm prog
0000000000003d98 d _DYNAMIC
0000000000003fa8 d _GLOBAL_OFFSET_TABLE_
0000000000002000 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
000000000000224c r __FRAME_END__
0000000000002088 r __GNU_EH_FRAME_HDR
0000000000004010 d __TMC_END__
0000000000004010 B __bss_start
w __cxa_finalize@@GLIBC_2.2.5
0000000000004000 D __data_start
0000000000001140 t __do_global_dtors_aux
0000000000003d90 d __do_global_dtors_aux_fini_array_entry
0000000000004008 d __dso_handle
0000000000003d88 d __frame_dummy_init_array_entry
w __gmon_start__
0000000000003d90 d __init_array_end
0000000000003d88 d __init_array_start
00000000000012c0 T __libc_csu_fini
0000000000001250 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
0000000000004010 D _edata
0000000000004018 B _end
00000000000012c8 t _fini
0000000000001000 t _init
00000000000010a0 T _start
0000000000004010 b completed.8060
0000000000004000 W data_start
00000000000010d0 t deregister_tm_clones
0000000000001180 t frame_dummy
0000000000001234 T libx1_api
00000000000011e6 T libx1_user
000000000000121d T libx_api
0000000000001189 T main
U puts@@GLIBC_2.2.5
0000000000001100 t register_tm_clones
U w_libx2_api
U w_libx_api