c - 如何回调到 exe 中的函数?

标签 c linux callback

我有一个针对 Windows 的书面代码,现在正在尝试移植到 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
    }
}

最佳答案

不幸的是,dlopen 不能满足许多​​其他张贴者所说的这个目的。它只能加载共享库。如果传递 NULL 而不是共享库路径,则可以查找运行时链接器尚未从主可执行镜像中剥离的任何符号(数量不多)。

但是,如果你想在没有使用 -rdynamic 编译的可执行文件中调用函数,请尝试 LD_PRELOAD'ing 你自己的共享库,它(在启动时)通过 找到你的可执行文件的真实路径>/proc/self/exe,内存映射它,然后读取该映射(或其他可执行文件头)上的符号表以定位和解释主可执行文件中的符号。

从那里开始,只需在您的共享库中定义一些与您希望调用的函数原型(prototype)相匹配的函数指针,为它们分配符号在二进制文件中的位置,然后正常调用函数指针.

关于c - 如何回调到 exe 中的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8652298/

相关文章:

c - 只保留重复模式的最后一行

c - 返回 c 中的连续 block

c - 删除链表中的第一个节点仍然在结果中显示节点

c - 为什么 --x; work and x-- 在递归代码中给出段错误

linux - 如何测试变量是否是 bash 中的字符串?

objective-c - 将 Objective C 回调转换回 Swift

javascript - 将类方法绑定(bind)到类外绑定(bind)的事件处理程序中的 AJAX 成功回调

linux - 如何在传出数据包上插入 VLAN 标记

正则表达式修剪字符串中一些不需要的字符

javascript - 如何让用户确认 ExtJs 中的组合框更改事件?