如何在编译时调用声明未知的函数

时间:2018-03-28 22:12:12

标签: c ffi

这基本上就是问题所在。

void call_function(void* func, const char* funcdecl, void* arguments) {

  // how do I do this?

  // some pseudo code
  for(i = 0; i < numargs; ++i) {
    if(funcdecl.args[i].type == TYPE_DOUBLE) {
      push funcdecl.args[i].doubleValue
    }
    ...
  }
  call func
  reslut.type = funcdecl.result_type;
  if(funcdecl.result_type == TYPE) {
    result.value = read_doulbe_from_stack();
  }
}


// nothing from here on is known before call_function.

double foobar(int a, int b, int c) {
  return a * 0.1 + b * 0.3 + c * 0.2;
}

typedef struct MyArgumentsStruct {
  int a;
  int b;
  int c;
} MyArgumentsStruct;

int main() {
  MyArgumentsStruct arguments;
  call_function( (void*)(foobar), "double foobar(int a, int b, int c);", &arguments);
}

所以基本上我不能将void*强制转换为函数类型,因为我不知道它。

我已经查找了gcc在编译为asm时所做的事情。当我正确理解它时,它会生成许多push指令来推送堆栈上的所有函数参数,然后使用call转到函数。然后该函数知道如何从堆栈中获取参数并将结果推回。

所以我的问题是,如何将参数从手动推送到堆栈? 我如何从堆栈中读取返回值?

1 个答案:

答案 0 :(得分:0)

如果您只想解决问题,请选择libffi之类的库(请参阅@SteveSummit链接的问题)。

如果您想了解它是如何完成的,您需要掌握装配。首先通过选择单个体系结构,单个调用约定,无参数来简化问题,稍后将解析C函数声明等等。只要您设法成功完成最简单的函数调用,就可以继续研究其余的细节 - 有很多!