如何回调exe内部的函数? (Linux)的

时间:2011-12-28 05:42:50

标签: c linux callback

我有一个针对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
    }
}

4 个答案:

答案 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所说,其他一切都会失败)?