同一应用程序上的dlopen/LoadLibrary

dlopen/LoadLibrary on same application

本文关键字:dlopen LoadLibrary 程序上 应用 应用程序      更新时间:2023-10-16

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

例如:

LoadLibrary("test.exe");

在一个名为CCD_ 3的程序中。

我测试了它,它似乎有效,但我不太确定它是否真的是受支持的行为。

从MSDN文档中。。。

系统在所有加载的模块上维护每个过程的参考计数。调用LoadLibrary会增加引用计数。调用FreeLibraryFreeLibraryAndExitThread函数会减少引用计数。当模块的引用计数达到零时或进程终止时(无论引用计数如何),系统都会卸载模块。

它会起作用的,只需记得打电话给FreeLibrary进行清理,如上所述。

您可能真正想要的是GetModuleHandle。

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

事实上,你试图做的事情甚至是一个特殊的情况。

lpModuleName[in,可选]

如果此参数为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:devscrap>gcc -oprint print.c
C:devscrap>print
OK

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

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

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上崩溃,但我认为这相当可疑。

你可以用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也在那里可用。