【问题标题】:Constructing a function call in C在 C 中构造函数调用
【发布时间】:2010-05-12 11:44:25
【问题描述】:

鉴于我有一个指向函数的指针(例如由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 作为编译器。

谢谢!

【问题讨论】:

  • ...准备好进行一些程序集黑客攻击,因为据我所知,纯 C 不会那样做。
  • ...或者您可以使用方便的库。

标签: c linux gcc function arguments


【解决方案1】:

您可能需要使用libffi

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      将你的参数解压成变量,然后调用函数。

      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 数组是否溢出。

      【讨论】:

      • 这不起作用,因为function 没有正确的类型。
      • functionint(*)() 类型,在 C 中相当于 int(*)(...)
      • 我也故意不回答参数解包问题,因为这个问题更倾向于调用函数的魔术,而不是参数。
      • 你说得对。但是arg0arg1等的类型在编译时是不知道的,所以这仍然行不通。
      • 例如,如果您正在创建一种解释性脚本语言并希望它支持在共享库中调用任意 C 函数,这将非常有用。
      猜你喜欢
      • 2015-03-17
      • 1970-01-01
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 2012-09-28
      • 1970-01-01
      相关资源
      最近更新 更多