2013-04-10 44 views
3

我需要检查动态库是否存在,以便稍后可以安全地调用使用此库的函数。确定动态库是否存在的多平台方法

有没有多平台的方法来检查这个?我的目标是MS Windows 7(VC++ 11)和Linux(g ++)。

+0

LoadLibrary调用应该失败,那么你可以知道。另外动态加载你从dll得到函数指针,如果指针为空,那么平台不支持那个平台上的那个函数。问题是什么? –

+0

如果库无法加载,那么我的应用程序崩溃 - 我想避免这种情况。这种情况是我使用了一些库(静态链接),期望它们的运行时助手动态库。 – Parobay

+0

对于POSIX变体(如Linux和Mac OSX),请查找['dlopen'](http://pubs.opengroup.org/onlinepubs/009695399/functions/dlopen.html)和['dlsym'](http:// pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html)。没有我知道的跨平台库,但它很简单,您可以使用非常类似的代码来检查Windows和Linux(相同的布局,只是不同的功能)。 –

回答

3

要动态“使用”共享库中的函数,需要该库不是可执行文件的一部分,因此您需要编写代码来加载库,然后使用该函数。可能有办法以便携的方式来做到这一点,但我不知道有任何代码可以做到这一点。

这不是很难写的代码。为“步骤”,它涉及到以下内容:

  1. 加载给定的文件(例如“XX”的名称的文库,然后将其转换为“xx.so”或在体系结构“xx.dll”具体的代码)。
  2. 根据索引(“函数编号1”)或名称(“函数等等”)查找函数,并返回地址。
  3. 对所有相关功能重复步骤2。
  4. 当不再需要库时,用提供的手柄关闭它。

如果第1步失败,那么你的库不存在(或以其他方式“行不通”),所以你不能调用函数在它...

显然,有很多设计接口来提供这种类型的功能的方法,以及你如何去做,取决于你的实际问题设置。

编辑:

为了澄清直接使用DLL,并使用一个使用从所述码动态加载之间的差值:

想象这是我们的“shared.h”,它定义为功能共享库 (可能有一些declspec(...)exportsymbol或其他类似的东西在一个真正的头,但我现在完全忽略)。

int func1(); 
char *func2(int x); 

在一段代码,直接使用DLL,你只是做:

#include <shared.h> 

int main() 
{ 
    int x = func1(); 
    char *str = func2(42); 

    cout << "x=" << x << " str=" << str << endl; 
    return 0; 
} 

相当直接的,对不对?

当我们使用动态的代码加载的共享库,它得到一个公平的有点复杂:

#include <shared.h> 

typedef int (*ptrfunc1)(); 
typedef char * (*ptrfunc2)(int x); 

int main() 
{ 
    SOMETYPE handle = loadlibrary("shared"); 
    if (handle == ERROR_INDICATOR) 
    { 
     cerr << "Error: Couldn't load shared library 'shared'"; 
     return 1; 
    } 
    ptrfunc1 pf1 = reinterpret_cast<ptrfunc1>(findfunc("func1")); 
    ptrfunc2 pf2 = reinterpret_cast<ptrfunc2>(findfunc("func2")); 

    int x = pf1(); 
    char *str = pf2(42); 

    cout << "x=" << x << " str=" << str << endl; 
    return 0; 
} 

正如你看到的,代码一下子得到了很多更加“混乱”。不要紧,你必须跳过寻找QObject的构造函数,或者更糟糕的是,从QObject继承。换句话说,如果你在你的代码中使用Qt,你可能会直接链接到“qt.lib”,如果你的应用程序没有安装Qt环境,你的应用程序将会崩溃。

+0

请注意:我使用eg。 qt.lib中的Qt函数(假设存在这样的lib),并且这些函数本身加载一个DLL。如果它们失败,我的整个应用程序将失败所以我想通过在试图加载之前手动检查DLL是否存在来防止这种情况。你明白吗? – Parobay

+0

是的,实现这一目标的唯一方法是不首先将'qt.lib'链接到您的应用程序中,然后使用您编写的代码来检查您是否可以加载'qt.dll',并且然后使用它。但是对于qt来说这将是一个非常糟糕的任务,因为它没有一个简单的界面。这是一大堆功能。而qt的全部重点是使代码可移植并在多个平台上编译相同。这将是一个更好的选择,建立一个安装程序,检查是否和/或确保安装qt'会导致应用程序的安装。 –

+0

我要说的是,如果你使用'qt.lib'链接,系统加载器将在应用程序启动时自动加载'qt.dll'或'qt.so' - 如果共享库不是在那里,它会使可执行文件的负载失效。这是可执行程序及其组成共享库如何在正常系统中加载的一部分。你不能改变它,除非你停止使用'qt.lib',这又意味着你不能只在代码中使用Qt函数。您必须通过一个接口来调用它们,以检查它们是否可用,如果不可用,则执行其他操作。 –

1

LoadLibrary调用应该失败,那么你可以知道动态库是否存在。还有动态加载,你会从动态库中获得函数指针,如果指针为空,那么平台不支持该平台上的那个函数。

在windows上您有LoadLibrary API来加载动态库。和GetProcAddress API在该lib中查找所需的函数。如果GetProcAddress针对您正在查找的特定功能返回NULL,则该平台不存在该功能。您可以记录然后决定回退。

相关问题