【问题标题】:C++: crossplatform way to retrieve a list of shared librariesC++:检索共享库列表的跨平台方式
【发布时间】:2015-04-20 23:34:08
【问题描述】:

是否可以以编程方式和跨平台方式检索链接到当前进程的共享库(*.dll、*.so、*.dylib)列表?

例如:

vector<string> getLinkedSharedLibraries() {
  // ...
}

vector<string> sharedLibraryList = getLinkedSharedLibraries();
for (list<string>::iterator it = sharedLibraryList.begin(); it != sharedLibraryList.end(); ++it)
  cout << *it << endl;

会返回:

/usr/lib/libz.1.dylib
/usr/lib/libSystem.B.dylib
...

我正在考虑使用操作系统命令,例如 Linux 上的 ldd 和 Mac 上的 otool -L,然后最终使用 [DY]LD_LIBRARY_PATH 来检索那里的绝对路径。但我在 Windows 上没有找到类似的方法。

或者,是否有任何现有的图书馆在做这种事情?

【问题讨论】:

  • 没有名为“C/C++”的语言,你的代码是C++。请更正您的标题。
  • windows上的解决方案比较失望:stackoverflow.com/questions/1993673/…
  • 旁白:为什么函数不返回库,而是将它们作为输出参数传递?通常不建议这样做 - 即很少有有效的用例。
  • 你是对的。我这样做是为了避免复制,但现代编译器似乎处理得更好(stackoverflow.com/questions/514908/…)。我正在编辑问题..

标签: c++ dll shared-libraries dylib


【解决方案1】:

这只是 Windows 做得更好的事情之一。您不需要工具,它提供了更多信息,而且很容易检索。

“知道”特定模块是否已加载并没有太多用例。要么你加载它,要么你没有。

#include <windows.h>
#include <tlhelp32.h>
#include <vector>
#include <iostream>
#include <sstream>

bool GetModules(std::vector<MODULEENTRY32> &modules)
{
    void* hSnap = nullptr;
    MODULEENTRY32 Mod32 = {0};

    if ((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId())) == INVALID_HANDLE_VALUE)
        return false;

    Mod32.dwSize = sizeof(MODULEENTRY32);
    while (Module32Next(hSnap, &Mod32))
    {
        modules.push_back(Mod32);
    }

    CloseHandle(hSnap);
    return true;
}


std::string ModuleToString(MODULEENTRY32 Mod32)
{
    auto to_hex_string = [](std::size_t val, std::ios_base &(*f)(std::ios_base&)) -> std::string
    {
        std::stringstream oss;
        oss << std::hex << std::uppercase << val;
        return oss.str();
    };

    std::string str;
    str.append("  =======================================================\r\n");
    str.append("  Module Name:             ").append(Mod32.szModule).append("\r\n");
    str.append("  =======================================================\r\n\r\n");
    str.append("  Module Path:             ").append(Mod32.szExePath).append("\r\n");
    str.append("  Load Count (Global):     ").append(std::to_string(static_cast<int>(Mod32.GlblcntUsage != 0xFFFF ? Mod32.GlblcntUsage + 1 : 0)).c_str()).append("\r\n");
    str.append("  Load Count (Process):    ").append(std::to_string(static_cast<int>(Mod32.ProccntUsage != 0xFFFF ? Mod32.ProccntUsage + 1 : 0)).c_str()).append("\r\n");
    str.append("  Base Address:            0x").append(to_hex_string(reinterpret_cast<std::size_t>(Mod32.modBaseAddr), std::hex).c_str()).append("\r\n");
    str.append("  Base Size:               0x").append(to_hex_string(Mod32.modBaseSize, std::hex).c_str()).append("\r\n\r\n");
    str.append("  =======================================================\r\n");
    return str;
}


int main()
{
    std::vector<MODULEENTRY32> modules;

    if (GetModules(modules))
    {
        for (auto &&it : modules)
        {
            std::cout<<ModuleToString(it)<<"\n";
        }
    }
    return 0;
}

【讨论】:

  • 谢谢,这很有用。现在,我正在寻找适用于 Mac 和 Linux 的等效代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-11
  • 2011-07-28
相关资源
最近更新 更多