dlopen / LoadLibrary在同一个应用程序上

时间:2012-07-31 13:45:22

标签: c++ c loadlibrary dlopen

我需要从我自己的应用程序中调用导出的符号 - 因此我需要知道在“自己”上调用dlopen / LoadLibrary是否安全。

一个例子是:

LoadLibrary("test.exe");

在名为test.exe的程序中。

我测试过它似乎有用,但我不太确定它是否真的受到支持。

3 个答案:

答案 0 :(得分:5)

来自MSDN文档here ...

  

系统维护所有已加载模块的每进程引用计数。调用 LoadLibrary 会增加引用计数。调用 FreeLibrary FreeLibraryAndExitThread 函数会减少引用计数。系统在其引用计数达到零或进程终止时卸载模块(无论引用计数如何)。

它会起作用,只需记住如上所述,通过致电FreeLibrary来清理自己。

非常想要的是GetModuleHandle

  

检索指定模块的模块句柄。该模块必须已由调用进程加载。

事实上,你所要做的甚至是一个特例。

  

lpModuleName [in,optional]

     

...

     

如果此参数为NULL, GetModuleHandle 将返回用于创建调用进程(.exe文件)的文件的句柄。

所以,试试这个......

#include <stdio.h>
#include <windows.h>

__declspec(dllexport) void print(void) {
  puts("OK");
}

main() {
  HMODULE mod = GetModuleHandle(0);
  FARPROC proc = GetProcAddress(mod, "print");
  proc();
  return 0;
}

......似乎有效:

C:\dev\scrap>gcc -oprint print.c

C:\dev\scrap>print
OK

对于dlopen,它看起来非常相似。

  

如果 filename 是NULL指针,则返回的句柄用于主程序。当给予 dlsym ()时,此句柄会导致在主程序中搜索符号,然后搜索程序启动时加载的所有共享库,然后搜索由 dlopen加载的所有共享库(),标记为 RTLD_GLOBAL

答案 1 :(得分:2)

你可以用dlopen()轻松地做到这一点 - 有一个伪句柄作为GNU扩展,RTLD_DEFAULT就像一个自己的句柄,所以你可以简单地跳过dlopen()调用并写:

dlsym(RTLD_DEFAULT, "entry_func");

例如:

#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <assert.h>

void print(void) {
  puts("OK");
}

int main() {
  void (*proc)(void) = dlsym(RTLD_DEFAULT, "print");
  assert(proc);
  proc();
  return 0;
}

请注意,您需要使用-rdynamic进行编译才能实现此目的。

根据最新的Solaris计算机上的联机帮助页RTLD_DEFAULT也可以使用。

答案 2 :(得分:1)

Windows上的快速测试:

#include <windows.h>
#include <stdio.h>

__declspec(dllexport) FARPROC Test() { 
    printf("It worked");
}

int main(int argc, char **argv) {
    HMODULE m = LoadLibrary(argv[0]);
    FARPROC test = GetProcAddress(m, "Test");
    test();
    return 0;
}

产生了以下输出:

It worked

我认为理论上并不保证它可能不会破坏其他版本的Windows,但我认为这是值得怀疑的。