代码之家  ›  专栏  ›  技术社区  ›  0x6adb015

在C语言中构造函数调用

  •  2
  • 0x6adb015  · 技术社区  · 15 年前

    假设我有一个指向函数的指针(由 dlsym() 例如)和类型化参数的链接列表,如何用这些参数构造C函数调用?

    例子:

    struct param {
       enum type { INT32, INT64, STRING, BOOL } type;
       union { int i32; long long i64; char *str; bool b; } value;
       struct param *next;
     };
     int call_this(int (*function)(), struct param *args)
     { 
         int result;
         /* magic here  that calls function(), which has a prototype of
         f(int, long long, char *, bool); , when args consist of a linked list of
         INT32, INT64, STRING, BOOL types. */
         return result;
     }
    

    操作系统是Linux。我希望该解决方案能够跨MIPS、PPC和x86(全部32位)体系结构进行移植,并使用GCC作为编译器。

    谢谢!

    3 回复  |  直到 15 年前
        1
  •  2
  •   Community CDub    8 年前

    用标准C支持任意函数签名是不可能的(至少我不知道有什么方法可以做到这一点)。如果你需要这个,我会去的 libffi 作为 Tom suggested .

    如果您希望支持的签名数量有限,那么可以检查类型字段并通过将无原型函数指针强制转换为正确的原型并自己提供正确的参数来适当地分派调用。强制转换函数指针是避免默认参数提升所必需的,但是即使没有强制转换,您仍然需要手动调度签名以访问正确的联合成员。这个过程可以通过使用您选择的脚本语言从签名列表中生成C代码来实现自动化。

        2
  •  6
  •   Tom Dalling    15 年前

    您可能需要使用 libffi .

        3
  •  0
  •   Didier Trosset    15 年前

    将参数解包成变量,然后调用函数。

    int a[10];
    int n = 0;
    while (args != NULL) {
        if (args->type == INT64) {
    #if __BIG_ENDIAN__
            a[n++] = args->value.i64 >> 32;
            a[n++] = args->value.i64 & 0xffffffff;
    #else
            a[n++] = args->value.i64 & 0xffffffff;
            a[n++] = args->value.i64 >> 32;
    #endif
        } else { /* all other types are pushed as 32 bits parameters */
            a[n++] = args->value.i32;
        }
    }
    result = (*function)(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
    

    您还必须检查不要溢出 a 数组。