gcc中的运行时参数(反向va_args / varargs)

我正在尝试对我正在研究的微控制器的解释器进行一些改进。 为了执行内置函数,我目前有这样的东西(虽然有点快):

function executeBuiltin(functionName, functionArgs) { if (functionName=="foo") foo(getIntFromArg(functionArgs[0])); if (functionName=="bar") bar(getIntFromArg(functionArgs[0]),getBoolFromArg(functionArgs[1]),getFloatFromArg(functionArgs[2])); if (functionName=="baz") baz(); ... } 

但它适用于资源非常有限的嵌入式设备(ARM),我需要大幅减少代码大小。 我想做的是有一个通用函数来调用具有不同参数的其他函数 – 如下所示:

 function executeBuiltin(functionName, functionArgs) { functionData = fast_lookup(functionName); call_with_args(functionData.functionPointer, functionData.functionArgumentTypes, functionArgs); } 

所以我希望能够调用标准的C函数并将其传递给它所需的任何参数(可能都是不同的类型)。 为此,我需要一个call_with_args函数。

我想避免重写每个函数来采取argc + argv。 理想情况下,每个被调用的函数都是完全标准的C函数。

这里有一个关于这个问题的讨论 – 但自1993年撰写该帖以来,有什么变化吗? 特别是当我在ARM上运行时,参数位于寄存器而不是堆栈中。 即使它不在标准C中,是否有任何GCC具体可以完成?


更新:看起来尽管根据规范行为是“未定义的”,看起来因为C调用的方式工作,你可以传递更多的参数到一个函数而不是它期望的一切都很好,所以你可以解压缩所有将参数放入uint32s数组中,然后可以将每个uint32传递给该函数。

这使得为​​调用编写“漂亮”代码变得更加容易,并且它似乎运行得很好(在32位平台上)。 唯一的问题似乎是传递64位数字并编译为64位x86,因为在这种情况下它似乎做了一些特别奇怪的事情。

是否有可能在编译时使用宏? 以下内容: https : //www.redhat.com/archives/libvir-list/2014-March/msg00730.html

如果需要运行时,可能会利用__buildin_apply_args()。

从本文档的第5.5节“ 参数传递 ”来看,似乎参数在寄存器和堆栈中都是通过的,就像今天的大多数平台一样。

使用“非标准C”我打算打包参数并使用一些asm()调用文档后面的函数。 但是,您仍然需要有关被调用函数的签名的最小信息(我的意思是,每个参数要传递多少位)。

从这个角度来看,我更愿意准备一个函数名数组,一个函数指针数组和一个枚举函数签名数组(每个参数的位数……你不需要区分void *和例如,char *和签名上的开关/案例,以及最后一个上的开关/案例。 所以我在这里报告了两个答案。

您可以执行非常简单的序列化来传递任意参数。 为每个传递的参数创建一个数组和memcpy sizeof(arg)字节。

或者您可以为函数参数创建结构。

每个函数都使用char *或void *。 然后传递一个指向带有该函数参数的结构的指针,或者定义一组宏或函数来编码和解码数组中的任意数据并将指针传递给该数组。