【问题标题】:Getting all functions with prefix in C在C中获取所有带前缀的函数
【发布时间】:2014-06-04 17:30:00
【问题描述】:

是否可以获得指向具有前缀的函数的函数指针?起初我以为 c 函数的名称在编译过程中丢失了。但随后,dlsym 返回指向指定名称的函数的指针。

所以如果有办法做这样的事情:

void * handle = dlopen(0, RTLD_NOW|RTLD_GLOBAL);
*(void **)(&fptr);
while(fptr = dlsym(handle, "prefix*")) {
   fptr(args);
}

【问题讨论】:

  • 只是为了迂腐:没有办法做这样的事情'In c'。您已经正确地注意到可能有一种方法可以在 上执行此操作。如果您具体了解该平台,您可能会得到更好的答案。
  • 我已经标记为 posix,因为 dlsymdlopen 是 posix。
  • Linux 动态加载器提供了这些功能,手册页讨论了dlsym() 搜索符号表树。检查实现这些的库的源代码可能会揭示一种枚举树中所有符号的方法。
  • 如果这完全是您的程序(因此您可以更改它的任何部分),您应该以简单的方式创建这些函数指针的数组。
  • 我不确定您手动调用它们是什么意思。如果你知道他们的名字,你可以用通常的方式称呼他们。你为什么要按照你想要的方式去做?

标签: c posix function-pointers


【解决方案1】:

为什么不做这样的事情:

#include <stdio.h>

void funcA(int n) { printf("funcA: %d\n", n); }
void funcB(int n) { printf("funcB: %d\n", n); }
void funcC(int n) { printf("funcC: %d\n", n); }

void (*funcs[3]) (int n) = {
    funcA,
    funcB,
    funcC
};

int main() {
    int i;
    for (i = 0; i < sizeof funcs / sizeof *funcs; ++i)
        funcs[i](i);
    return 0;
}

【讨论】:

    【解决方案2】:

    这不是内置方式,而且我认为没有内置方式...您可以解析 nm,但这很糟糕。

    但是如果你正在构建一个插件,你可以使用一个已知的符号来获取所有的符号。

    lib.c

    char ** functions()
    {
        static char * f[3] = {"function1","function2",NULL};
        return f;
    }
    
    void function1()
    {
        printf("function1\n");
    }
    
    void function2()
    {
        printf("function2\n");
    }
    

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <dlfcn.h>
    #include <errno.h>
    
    typedef char ** (*functions)(void);
    typedef void (*voidFunc)(void);
    
    int main(int argc, const char * argv[])
    {
        void * ref = dlopen("/abs/path/to/libExample.dylib",  RTLD_LAZY | RTLD_LOCAL);
        if (!ref)
        {
            printf("filed to open dylib: %i",errno);
        }
    
        functions f = dlsym(ref, "functions");
    
        if (f)
        {
            char** fnames = f();
            char * fname = NULL;
            for (int i = 0; 1 ; i++)
            {
                fname = fnames[i];
                if (fname) {
                    voidFunc g = dlsym(ref, fname);
                    if (g)
                    {
                        g();
                    }
                }else{
                    break;
                }
            }
        }
        dlclose(ref);
        return EXIT_SUCCESS;
    }
    

    输出:

    function1
    function2
    Program ended with exit code: 0
    

    不是 linux 方式,但在 OS X 上,有一些额外的东西可能会更容易:

    /*
     * Structure filled in by dladdr().
     */
    typedef struct dl_info {
            const char      *dli_fname;     /* Pathname of shared object */
            void            *dli_fbase;     /* Base address of shared object */
            const char      *dli_sname;     /* Name of nearest symbol */
            void            *dli_saddr;     /* Address of nearest symbol */
    } Dl_info;
    
    extern int dladdr(const void *, Dl_info *);
    

    【讨论】:

    • 一个名为 functions 的变量非常令人困惑(至少对我而言)。
    • 是的,更令人困惑的是它也是一个 typedef :)
    猜你喜欢
    • 1970-01-01
    • 2021-02-13
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-13
    相关资源
    最近更新 更多