C++ 同一应用程序上的dlopen/LoadLibrary

C++ 同一应用程序上的dlopen/LoadLibrary,c++,c,loadlibrary,dlopen,C++,C,Loadlibrary,Dlopen,我需要从我自己的应用程序调用导出的符号-因此我需要知道在“您自己”上调用dlopen/LoadLibrary是否安全 例如: LoadLibrary("test.exe"); 在名为test.exe的程序中 我对它进行了测试,它似乎可以工作,但我不太确定它是否真正受支持。在Windows上的快速测试: #include <windows.h> #include <stdio.h> __declspec(dllexport) FARPROC Test() {

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

例如:

LoadLibrary("test.exe");
在名为
test.exe的程序中


我对它进行了测试,它似乎可以工作,但我不太确定它是否真正受支持。

在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;
}

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

< P>从MSDN文档…

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

它会起作用的,只要记得打电话给自己清理一下,如上所述

你可能真正想要的是

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

事实上,你想做的只是一个特例

lpModuleName[输入,可选]

如果此参数为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;
}
例如,它看起来非常相似

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


您可以通过
dlopen()
轻松实现这一点-有一个伪句柄作为GNU扩展名提供,
rtldu 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;
}
定义GNU源
#包括
#包括
#包括
作废打印(作废){
卖出(“OK”);
}
int main(){
作废(*proc)(作废)=dlsym(RTLD_默认,“打印”);
断言(proc);
proc();
返回0;
}
请注意,您需要使用
-rdynamic
进行编译才能使其正常工作


根据最近Solaris机器上的手册页,那里也有默认的
RTLD\u

如果它在您自己的应用程序中,为什么不直接调用它呢?它是在插件架构中。实现(有点像COM)是基于DLL/SOs的机制加载的。此机制适用于文件名。现在我们遇到了在应用程序中定义一些插件(至少作为备份)的用例。因此,我们需要扩展加载程序。如果我们可以通过dlopen/LoadLibrary安全地从应用程序加载,我们就可以以统一的方式处理所有情况。目前,映射存储在一个std::map中,它将一个类型映射到一个dll/so。因此,NULL不是一个可用的选项,如果可能,应避免特殊处理…根据手册页,可以使用dlopen(nullptr);不管出于什么原因,RTLD_默认值对我不起作用。由于我现在在Windows上使用GetModuleHandle,我也可以在Linux上使用dlopen(nullptr)。。。[因为我已经需要以不同的方式处理宿主程序…]
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;
}