【发布时间】:2022-06-10 19:51:14
【问题描述】:
我正在使用firewall 为 stm32 编程。要打开防火墙,必须使用呼叫门。或多或少通常的方法是编写一个带有可变参数的函数,并使用 switch 语句中的第一个参数在不同的函数之间切换。
int function1_outside(int arg1)
{
int status;
// disable interrupts
status = CallGate(ID1, arg1);
// enable interrupts
return status;
}
int CallGate(FunctionID eID, ...)
{
va_list arguments;
int status;
/* Initializing arguments to store all values */
va_start(arguments, PrimaskParam);
switch (eID)
{
case ID1:
{
int arg1;
/* Retrieve argument(s) */
arg1 = va_arg(arguments, int);
// Call the real function
status = function1_inside(arg1);
break;
}
case ID2:
{
// do more ...
break;
}
}
/* Clean up arguments list*/
va_end(arguments);
return status;
}
int function1_inside(int arg1)
{
int result;
// do stuff
result = arg1 + 1;
return result;
}
这种方法的最大问题是保持所有部分同步。
有没有减少需要保持同步的部分的好方法?
【问题讨论】:
-
从我幼稚的角度来看,您可以使用函数指针作为第一个参数,使用 void 指针作为第二个参数,允许您使用指向函数的指针来选择函数并允许您将参数的结构作为第二个参数传递,不是吗?这将最大限度地减少要保持同步的部分。
-
我已经想到了类似的方向。一个问题是获取函数指针。带有调用门的部分是单独编译的。您必须提前通过调用门或在激活防火墙之前传输函数指针。但是您还必须使用指针维护结构。
-
另外一件事是如何从一个带有 va_list 的函数转换为多个普通函数?
-
CallGate 必须是可变参数吗?否则,您可以将其声明为
void CallGate(void (*function)(void*), void* data),从而接受要调用的函数和函数的参数。至于获取函数指针,你可以在外面做extern void function_inside(void*); CallGate(&function_inside, (void*)function_parameters); -
我建议保留开关以本地化功能,这样您只需在头文件中进行简单枚举即可在 2 个编译单元之间共享它们。对于参数,在标题中将其声明为:
extern void CallGate(int code, ...);。然后将您的子函数声明为:function1_inside(va_list ap);其中ap是指向通过va_start(ap, code);获得的下一个参数的指针。然后在子函数中,您可以检索特定于该函数的所有参数。