我有一个针对Windows的书面代码,现在我正在尝试移植到Linux,但不确定它是否可行。
我的问题:我正在尝试回调共享库中可执行文件中的函数。我该怎么做?
我对Linux很陌生,所以如果我的问题太低,请跟我一起。
这是编译输出:
Output:
build/release-linux-ppc64/ioq3ded.ppc64
build/release-linux-ppc64/ioquake3.ppc64
build/release-linux-ppc64/baseq3/cgameppc64.so
build/release-linux-ppc64/baseq3/qagameppc64.so
build/release-linux-ppc64/baseq3/uippc64.so
build/release-linux-ppc64/missionpack/cgameppc64.so
build/release-linux-ppc64/missionpack/qagameppc64.so
build/release-linux-ppc64/missionpack/uippc64.so
make[2]: Entering directory `/r/home7/XXX/ioquake3'
make[2]: `build/release-linux-ppc64/ioq3ded.ppc64' is up to date.
make[2]: `build/release-linux-ppc64/ioquake3.ppc64' is up to date.
LD build/release-linux-ppc64/baseq3/cgameppc64.so
LD build/release-linux-ppc64/baseq3/qagameppc64.so
LD build/release-linux-ppc64/baseq3/uippc64.so
LD build/release-linux-ppc64/missionpack/cgameppc64.so
LD build/release-linux-ppc64/missionpack/qagameppc64.so
LD build/release-linux-ppc64/missionpack/uippc64.so
这是我运行以执行程序的命令,这就是为什么我认为“ioq3ded.ppc64”是我的可执行文件。
./ioq3ded.ppc64 +set fs_game Mod +set sv_pure 0 +set vm_game 0 +set vm_cgame 0 +set vm_ui 0 +set dedicated 1 +exec something_117.cfg
这是Windows的代码:
//Called function
__declspec(dllexport) void UnLinkLinkroutingcache( void )
{
//code
}
//Callback location
#include<windows.h>
typedef void (* fUnLinkLinkroutingcache_t)( void );
void fUnLinkLinkroutingcache( fUnLinkLinkroutingcache_t pUnLinkLinkroutingcache )
{
pUnLinkLinkroutingcache(); return;
}
fUnLinkLinkroutingcache_t pUnLinkLinkroutingcache;
void callUnlinkLink(void)
{
HMODULE hLib;
//fUnLinkLinkroutingcache_t pUnLinkLinkroutingcache;
hLib = LoadLibrary(TEXT("ioquake3.exe"));
if (hLib == NULL)
{
//Module not found, permission denied, ...
return 0; //inform caller of error
}
pUnLinkLinkroutingcache = (fUnLinkLinkroutingcache_t)GetProcAddress(hLib, TEXT("UnLinkLinkroutingcache"));
if ( pUnLinkLinkroutingcache == NULL)
{
return 0;
}
fUnLinkLinkroutingcache(pUnLinkLinkroutingcache);
}
我试图将此代码移植到Linux,但我似乎无法加载exe。
//Called function
extern void UnLinkLinkroutingcache( void )
//Callback location
void callUnlinkLink(void)
{
void* handle;
void (*initializer)(void);
FILE *fp;//zgzg2020
fp = fopen("HereIsMe.txt", "a");
if( fp != NULL )
{
fprintf(fp, "%d", 1 );
fprintf(fp, "\n" );
}
fclose(fp);
handle = dlopen("./ioq3ded.ppc64", RTLD_LAZY);
if(handle == NULL) {
// report error ...
fp = fopen("ICantFindFile.txt", "a");
if( fp != NULL )
{
fprintf(fp, "%d", 1 );
fprintf(fp, "\n" );
}
fclose(fp);
exit(1);return;
} else {
initializer = dlsym(handle,"UnLinkLinkroutingcache");
if(initializer == NULL) {
// report error ...
fp = fopen("ICantFindFfunction.txt", "a");
if( fp != NULL )
{
fprintf(fp, "%d", 1 );
fprintf(fp, "\n" );
}
fclose(fp);
exit(1);return;
} else {
// cast initializer to its proper type and use
(*initializer)();
}
// use the result in a call to dlsym
}
}
答案 0 :(得分:2)
不幸的是,dlopen
不足以达到这个目的,正如许多其他海报所说的那样。它只能加载共享库。如果传递NULL而不是共享库路径,则可以查找运行时链接程序未从主可执行映像中删除的任何符号(没有很多)。
但是,如果要在不使用-rdynamic
编译的可执行文件中调用函数,请尝试LD_PRELOAD'自己的共享库(启动时)通过/proc/self/exe
找到可执行文件的实际路径,内存映射它,然后读取该映射(或其他可执行标头)上的符号表,以定位和解释主可执行文件中的符号。
从那里开始,只需要在共享库中定义一些函数指针,这些函数指针与您要调用的函数的原型相匹配,为它们分配符号在二进制文件中的位置,并将函数指针调用为正常
答案 1 :(得分:1)
Linux中不能dlopen
个可执行文件 - 该功能仅适用于共享库(.so
,大致相当于Windows上的.dll
。)
你想要完成什么?
答案 2 :(得分:0)
函数dlopen()加载由以null结尾的字符串文件名命名的动态库文件,并为动态库返回一个不透明的“句柄”。如果filename为NULL,则返回的句柄用于主程序。这意味着它必须是动态库。
答案 3 :(得分:0)
如果ioq3ded.ppc64真的是.so(看起来不像),你检查一下它出口了什么吗?
当您从dlopen获得null返回时,您是否检查过errno(假设它是一个.so文件,如@duskwuff所说,其他一切都会失败)?