我可以将 char* 数组而不是几个参数传递给函数吗?

Can I pass char* array instead of several arguments to a function?

我正在尝试编写一个程序,该程序将 运行 来自动态库的函数,其名称、参数及其类型由用户输入。我可以使用 dlsym(func_name) 获得指向此函数的 void* 指针,但我事先不知道参数的类型及其数量,因此我无法以正常方式取消引用此指针。

如果我将所有参数的字节表示复制到一个 char * 数组中,我可以用这个数组作为参数调用函数吗?例如,当在程序集中调用 printf 时,我可以将参数和格式字符串压入堆栈并调用 printf。也许我可以在 C 中做类似的事情,或者使用程序集插入?

例如,假设函数是 void func(int, double);,我得到参数 int adouble b。然后我会创建一个数组:

char buf[sizeof(int) + sizeof(double)]
memcpy(buf, &a, sizeof(int))
memcpy(buf + sizeof(int), &b, sizeof(double))

并将其用作压入堆栈的参数。

用户输入函数名称、描述其类型的字符串以及参数本身。例如:

func_name
viid
5
6
2.34

func_name 是将在 dlsym 中使用的函数的名称。 viid 表示该函数具有 void func_name(int, int, double) 类型(第一个 char 是 return 类型,其余是参数。v = void,i = int,d = double)。剩下的就是争论了。

不,除非可能在纯粹在堆栈上传递参数的 ABI 中。任何计算环境都有如何传递参数的规范。 (此规范是平台的应用程序二进制接口 [ABI] 规范的一部分。)参数类型和大小会影响它们是在通用寄存器、浮点寄存器还是其他位置传递,以及它们如何对齐。很少(如果有的话)这样的规范将参数作为字节的原始转储传递到堆栈。

可以编写代码来解码参数的描述并构建调用函数所需的状态。这样的代码至少需要部分用汇编或各种语言扩展来编写。 (我希望有些人可能已经编写了这样的代码并使其可用,但没有这样的参考。)对于大多数情况来说,这可能是一个实施起来成本过高的解决方案;您应该寻求其他方法来实现您的基本目标。

如果 ABI 确实指定所有参数都放在堆栈上,则可以在包含 unsigned char:

数组的结构中传递任意参数
  • 必须确定最大大小,例如struct { unsigned char bytes[128]; },因为标准C 不支持可变大小的结构。
  • 对于具有最严格对齐方式的参数,结构必须按照要求对齐。
  • 所有参数的字节必须在结构内正确对齐。
  • 函数将通过将结构本身作为参数传递来调用。请注意,ABI 必须说明即使是大型结构也会直接在堆栈上传递。有人可能会说传递了指向结构(的副本)的指针。

请注意,ABI 可能包含影响函数调用的其他细节,例如规定某个寄存器必须包含参数的数量或以某种方式设置,即使它本身不包含参数。