在软件开发中,版本管理至关重要。但是,某些极端情况,需要同时运行一个接口的不同版本的函数,那么有没有可能实现呢。
比如下面有两个版本的 fun
函数,他们函数签名,都完全一样,能在一个程序中同时调用这两个函数吗?
1 2 3 4 5 6 7 8 9
| const char* fun() { return "fun version 1"; }
const char* fun() { return "fun version 2"; }
|
在上述代码中,我们定义了两个版本的函数 fun()
,分别位于目录 v1/
和 v2/
下。接下来,我们将这两个版本编译成共享库(.so 文件):
1 2
| g++ -shared -fPIC -o v1/fun.so v1/fun.cpp g++ -shared -fPIC -o v2/fun.so v2/fun.cpp
|
然后,我们在 main.cpp
中调用这两个共享库中的 fun
函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <dlfcn.h> #include <iostream>
typedef const char* (*fun_ptr)();
int main() { void* handle_v1 = dlopen("v1/fun.so", RTLD_LAZY); fun_ptr fun_v1 = reinterpret_cast<fun_ptr>(dlsym(handle_v1, "_Z3funv"));
void* handle_v2 = dlopen("v2/fun.so", RTLD_LAZY); fun_ptr fun_v2 = reinterpret_cast<fun_ptr>(dlsym(handle_v2, "_Z3funv"));
std::cout << "Calling v1/fun(): " << fun_v1() << std::endl; std::cout << "Calling v2/fun(): " << fun_v2() << std::endl;
dlclose(handle_v1); dlclose(handle_v2);
return 0; }
|
在上述代码中,我们使用了 dlsym
函数来获取函数指针,注意参数中的符号是 _Z3funv
,而不是函数名fun
。在编译并运行程序之前,你可以通过 nm v1/fun.so
查看符号表以获取正确的符号名。有关符号修饰请查看 符号修饰
最后,编译并运行程序:
1 2
| g++ main.cpp -ldl ./a.out
|
通过以上步骤,你将能够看到以下输出结果:
1 2
| Calling v1/fun(): fun version 1 Calling v2/fun(): fun version 2
|
通过 dl 库,我们发现在一个程序中同时调用这一个函数的不同版本是可行的。(实际项目中一定要避免这种情况,做好版本管理)
上述示例代码可在 https://github.com/wenyg/dynamic_link_example 查看