【问题标题】:How to find boost runtime version如何找到 boost 运行时版本
【发布时间】:2013-11-22 08:33:37
【问题描述】:

我正在编写一个使用 boost 的 C++ 库。

在这个库中,我想包含有关用于编译我的库的二进制版本的 boost 版本的信息。 我可以使用宏BOOST_VERSION,这很好。

我还想确定 boost 的运行时版本,以便与用于编译我的库的 boost 版本进行比较。显然我不能使用宏,因为它会在编译时给我硬编码版本,而不是在运行时。

我需要的是 boost 中的一个函数(比如boost::get_version())。有没有办法在 boost 中做到这一点?

【问题讨论】:

  • 为什么在运行时需要版本?你想解决什么问题?
  • 我正在使用 boost-python 将 c++ 库包装到 python。我想在我的库中创建一个函数来完成用户安装的完整报告。当出现问题时,我可以要求用户将执行结果发送给我:$ python -c "import mylib; print mylib.info()" 以获取有关其安装的完整信息

标签: c++ boost


【解决方案1】:

您可以使用宏创建如下代码:

std::cout << "Using Boost "     
          << BOOST_VERSION / 100000     << "."  // maj. version
          << BOOST_VERSION / 100 % 1000 << "."  // min. version
          << BOOST_VERSION % 100                // patch version
          << std::endl;

这适用于 boost 1.51.x 及更高版本。不确定这是否是您正在寻找的东西,我会继续看看是否有办法以更优雅的方式从当前加载的 dll 中获取它。

附录:

要查找运行时版本:

在查看了 Boost 系统之后,您似乎可以做您正在寻找的最简单的方法是拥有平台相关代码,该代码在编译时用于生成不同版本的可执行文件。

对于 Windows:

您需要使用GetFileVersionInfoEx APIGetFileVersionInfo API 查询DLL 的版本,您还需要考虑操作系统是32 位还是64 位,所以这里有一些可能有用的代码:

typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS IsWow64ProcessFunc;

BOOL is64BitOS()
{
    BOOL retval= FALSE;
    // need to check if the OS is 64 bit, and we cant therefore indiscrimately call the 64 bit function for this, so we use the following:
    IsWow64ProcessFunc= (LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle(TEXT("kernel32")),"IsWow64Process");

    if(IsWow64ProcessFunc != NULL)
    {
        if (!IsWow64ProcessFunc(GetCurrentProcess(),&bIsWow64))
        {
            // your error handling code in here
        }
    }
    return retval;
}

然后我们可以利用一段直接的代码来获取 DLL 的版本:

void myWindowsDLLVersionChecker()
{
    DWORD  versionHandle = NULL;
    UINT   size      = 0;
    LPBYTE buffer  = NULL;
    DWORD  versionSize   = GetFileVersionInfoSize( szVersionFile, &versionHandle);

    if (verSize != NULL)
    {
        LPSTR versionData = new char[versionSize];

        if (GetFileVersionInfo( szVersionFile, versionHandle, versionSize, versionData))
        {
            if (VerQueryValue(versionData,"\\",(VOID FAR* FAR*)&buffer,&size))
            {
                if (size)
                {
                    VS_FIXEDFILEINFO *versionInfo = (VS_FIXEDFILEINFO *)buffer;
                    if (versionInfo->dwSignature == 0xFEEF04BD)  // value from http://msdn.microsoft.com/en-us/library/windows/desktop/ms646997(v=vs.85).aspx
                    {
                        if(is64BitOS())    //  if it is true then its a 64 bit Windows OS
                        {
                                major =     (versionInfo->dwProductVersionMS >> 16) & 0xff;
                                minor =     (versionInfo->dwProductVersionMS >>  0) & 0xff;
                                revision =  (versionInfo->dwProductVersionLS >> 16) & 0xff;
                                build =     (versionInfo->dwProductVersionLS >>  0) & 0xff;
                        } 
                        else //  32 bit Windows OS
                        {
                                major =     HIWORD(versionInfo->dwProductVersionMS);
                                minor =     LOWORD(versionInfo->dwProductVersionMS);
                                revision =  HIWORD(versionInfo->dwProductVersionLS);
                                build =     LOWORD(versionInfo->dwProductVersionLS);
                        }
                    }
                }
            }
        }
        delete[] versionData;
    }
}

对于 Linux:

目前非常不记得代码,但是这里是内存中的部分解决方案(我现在手头没有 Linux 机器,稍后会更详细地检查这个,但应该只适用于次要的最多修改)。

void myLinuxDLLVersionChecker() 
{
    // call readelf as an external proces son libboost_system.so, 
    // and use the information returned to extract the version from.
    // or use something like
    setenv("LD_TRACE_LOADED_OBJECTS", "1", 1);
    FILE *ldd = popen("/lib/libboost_system.so");
    //  information from http://linux.die.net/man/8/ld.so
    // the above pretty much replicates ldd's output, so you can pick out the version
}

两者结合:

要在多个操作系统中实现同样的事情,您可能必须使用类似的东西:

#ifdef __unix__                    /* __unix__ is usually defined by compilers targeting Unix systems */
void detectBoostDllVersion()  // does not have to be void, can be whatever you need
{
    myLinuxDLLVersionChecker();
}
#elif defined(_WIN32) || defined(WIN32)     /* _Win32 is usually defined by compilers targeting 32 or   64 bit Windows systems */
void detectBoostDllVersion()  // has to match the same return type as the previous version
{
    myWindowsDLLVersionChecker();
}
#endif

现在取决于为哪个操作系统编译,detectBoostDLLVersion() 函数将指向正确的函数:)

【讨论】:

  • 这正是我为获得 boost 编译时版本所做的。现在我想要 boost 运行时版本 的东西。感谢您的调查。
  • 好了,添加了windows和linux的示例代码,可以扩展原理支持__arm__等多个其他目标
  • 让我知道这对您有何帮助,或者如果您需要更多信息:)
  • 绝对是唯一的出路。不过,这非常复杂。只是为了得到一个版本号。非常感谢您的调查。它可以推广到访问任何库的版本号。我想我会在 boost 库中提出功能请求。让我们看看他们怎么说。
  • 是的,我同意,这不是获取版本号的一种非常优雅的方式。如果它有助于让我知道功能请求的详细信息,我也可以尝试并支持它(尽管它不是我过去需要的功能,但我绝对认为它应该比找到它更容易)数量优势: )
【解决方案2】:

在 boost 中没有这样的功能,我认为你只能扫描二进制文件来寻找这个东西(例如 linux 中的ldd)。

【讨论】:

  • 如果可能的话,我希望解决方案是跨平台的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-08
  • 1970-01-01
  • 2018-09-28
  • 2022-01-10
  • 2020-07-15
  • 2021-12-22
  • 2019-02-05
相关资源
最近更新 更多