类似于运行时的预处理器

something like preprocessors at runtime

在我的应用程序中,我使用了库 x2.0 中的新函数,该函数在 x1.0 版本中找不到,但我想保持向后兼容性。

我动态地 link 使用那个库,当我在执行新函数之前使用简单的 if 条件检查库版本时它不起作用,因为在启动期间 exe 搜索并解析所有函数当我 运行 将应用程序 link 编辑到旧版本时,它给我错误。

在运行时我希望 exe 检查 lib 版本并执行新功能或不根据该版本执行它。

是否可能,如果可能,

我该怎么做才能实现这一目标?

处理与第三方库的向后兼容性的一种方法是围绕它创建一个包装器 library/source 文件,并确保您的应用程序永远不会从任何第三方库调用任何函数其他地方。

假设您依赖于提供两个头文件 "foo.h" 和 "bar.h" 的第三方库。在库的版本 1 中,文件可能如下所示:

foo.h:

void foo1();
int foo2();

bar.h:

void bar1(int);
int bar2(int);

比方说,他们在版本 2 中扩展了界面,现在它们看起来像:

foo.h:

void foo1();
int foo2();
double foo3();

bar.h:

void bar1(int);
int bar2(int);
int bar3(double);

在您的应用程序中,您希望在与库的版本 2 链接时能够使用 foo3()bar3(),但您希望能够优雅地处理缺少这些功能的问题在库的版本 1 中。

您可以使用以下方法来完成此操作。

为库创建一个包装器 .h 文件。

foo_bar_wrapper.h:

namespace foo_bar_wrapper
{
    void foo1();
    int foo2();
    double foo3();
    void bar1(int);
    int bar2(int);
    int bar3(double);
}

然后,将它们实现为传递给第三方库。

foo_bar_wrapper.h:

#include "foo.h"
#include "bar.h"

namespace foo_bar_wrapper
{
    void foo1() { ::foo1(); }
    int foo2() { return ::foo2(); }
    double foo3() { return ::foo3(); }
    void bar1(int x) { return ::bar1(x); }
    int bar2(int x) { return ::bar2(x); }
    int bar3(double x) { return ::bar3(x); }
}

但是,由于库的第 1 版不支持 foo3bar3,您可以使用:

namespace foo_bar_wrapper
{
    void foo1() { ::foo1(); }
    int foo2() { return ::foo2(); }

    double foo3() 
    {
#if FOO_LIBRARY_VERSION > 1
        return ::foo3();
#else
        // Deal gracefully with version 1
#endif
    }

    void bar1(int x) { return ::bar1(x); }
    int bar2(int x) { return ::bar2(x); }

    int bar3(double x)
    {
#if FOO_LIBRARY_VERSION > 1
       return ::bar3(x);
#else
        // Deal gracefully with version 1
#endif
    }

}

确保在构建应用程序时正确定义 FOO_LIBRARY_VERSION

我认为最好的答案是对同一个 dll 使用隐式和显式链接 默认情况下,加载程序将加载 dll,然后在您的代码中使用 LoadLibrary 和 GetProcAddress 获取旧版本库中不存在的 API

  HINSTANCE hinstLib; //Handle to the DLL
    // MYPROC ProcAddress; //Pointer to the function

   hinstLib = LoadLibrary("x.dll");
   FOO3 myFunc = (FOO3) GetProcAddress(hinstLib, "foo3");