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会增加引用计数。调用FreeLibrary或FreeLibraryAndExitThread函数会减少引用计数。当模块的引用计数达到零或进程终止时(无论引用计数如何),系统卸载模块 它会起作用的,只要记得打电话给自己清理一下,如上所述 你可能真正想要的是 检索指定模块的模块句柄。调用进程必须已加载该模块 事实上,你想做的只是一个特例 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;
}