如何在 onecodebase 中支持具有不同命名空间的两个版本的 third-party 库

How to support two versions of third-party libraries with different namespaces in onecodebase

我有两个版本的 third-party C++ 库(lib.so 和 header 文件) 在一个版本中,所有 classes/enums/structs 都在命名空间“A”中 在另一个版本中,它们位于命名空间“B”中 header 和 lib.so 名称在两个版本中都相同

我怎样才能拥有相同的代码库,以便我可以支持两个版本。像这样

if (myVersion == "1.0") {
    /* pick all the symbols from namespace "A"*/
} else {
    /* pick all the symbols from namespace "B"*/
}

您在代码中建议的是在运行时确定它,这在 C++ 中是不可能的。

如果您的版本不变,您可以将其声明为宏并使用预处理器进行调节。

如评论中所述,不建议使用 using namespace,命名空间别名会更好。

#if VERSION == 1000 //...
namespace My = A;
#else
namespace My = B;
#endif

//使用我的::...

但是,如果您坚持使用using namespace

#define VERSION //your version

...

#if VERSION == 1000 //or something like that to mark 1.0.0.0
using namespace A;
#else
using namespace B;
#endif

使用下面的代码,我创建了两个包装器 .so(一个带有 version1 lib 和 -DVERSION=1,另一个带有 version2 lib 和 -DVERSION=2) 假设它们是 wlib1.so 和 wlib2.so

我将命名空间 A 或 B 中的 API(取决于我正在编译的内容)包装在 extern "C"

例如:

#define VERSION //your version

extern "C"
{
#if VERSION == 1 //or something like that to mark 1.0.0.0
using namespace A;
#else
using namespace B;
#endif
 void foo_wrapper() {
  foo();
  // wlib1.so will have A::foo() and wlib2.so will have B::foo()
}
}

现在在用户端,我在 运行 时间使用了这样的东西:

using foo_t = void (*)();
foo_t foo_fp = nullptr;

void init(int ver)
{
std::string lib = "";
if (ver == 1) {
   lib = "wlib1.so";
} else {
   lib = "wlib2.so";
}

void* handle = dlopen(lib.c_str(), RTLD_LAZY);
foo_fp = reinterpret_cast<foo_t>(dlsym(handle, "foo_wrapper"));
}

/* use init(ver) before calling anything */
foo()
{
   foo_fp();
}

因此用户可以在运行时间通过ver.

进行控制