C-将带参数的函数传递到包装器执行器
有没有一种方法可以在C中构建包装器函数,如下所示:C-将带参数的函数传递到包装器执行器,c,C,有没有一种方法可以在C中构建包装器函数,如下所示: void wrapper(void *func) { // Set up func([same arguments as func was passed in with]); // Clean up } void foo(int x, int y); void bar(char *z); wrapper(foo(1, 2)); wrapper(bar("Hello")); 似乎您必须在wrapper中传递arumges,或者只
void wrapper(void *func) {
// Set up
func([same arguments as func was passed in with]);
// Clean up
}
void foo(int x, int y);
void bar(char *z);
wrapper(foo(1, 2));
wrapper(bar("Hello"));
似乎您必须在wrapper
中传递arumges,或者只支持func
的一种方法头。我已经写了很多Javascript。。。当然,这在JS中是可能的。您考虑过(ab)使用预处理器吗
#include <stdio.h>
#define wrapper(f) /* Set up */\
f; \
/* Clean up */
void foo(int x, int y) {
printf("x: %d; y: %d\n", x, y);
}
void bar(char *str) {
printf("str: %s\n", str);
}
int main(void) {
wrapper(foo(42, 11));
wrapper(bar("hello world"));
}
#包括
#定义包装器(f)/*设置*/\
f\
/*清理*/
无效foo(整数x,整数y){
printf(“x:%d;y:%d\n”,x,y);
}
空栏(字符*str){
printf(“str:%s\n”,str);
}
内部主(空){
包装物(foo(42,11));
包装(酒吧(“你好世界”);
}
为了详细说明为什么我在(ab)用法中添加了ab前缀,我会毫不犹豫地使用任何最能表达问题的解决方案,而不考虑胡杨的态度。然而,我认识到,有时我们无法控制我们所受的限制,而且往往制定政策来严格限制宏的使用。不幸的是,那些受这些愚蠢政策束缚的人不会觉得这篇文章太有帮助
在上面的一条评论中,我建议“如果你想从Javascript中获得一个特性,你可能应该用Javascript编写你的代码……”
经过一夜之间的思考,我得出结论,与您要求的功能类似的功能实际上是可行的,在C。。。所以我承认,我错了
下面是一个模拟Javascript如何处理函数的示例
#include <stdio.h>
struct argument;
typedef struct argument argument;
typedef void function(argument *);
struct argument {
function *function;
/* for foo() */
int x;
int y;
/* for bar() */
char *str;
};
void wrapper(argument *a) {
// set up
a->function(a);
// clean up
}
void foo(argument *a) {
printf("x: %d; y: %d\n", a->x, a->y);
}
void bar(argument *a) {
printf("str: %s\n", a->str);
}
#define foo(...) wrapper(&(argument){ .function = foo, __VA_ARGS__ })
#define bar(...) wrapper(&(argument){ .function = bar, .str = "", __VA_ARGS__ })
int main(void) {
foo(.x = 42, .y = 11);
bar(.str = "hello world");
}
#包括
结构参数;
typedef结构参数;
typedef void函数(参数*);
结构参数{
功能*功能;
/*for foo()*/
int x;
int-y;
/*对于bar()*/
char*str;
};
无效包装器(参数*a){
//设立
a->功能(a);
//清理
}
void foo(参数*a){
printf(“x:%d;y:%d\n”,a->x,a->y);
}
无效条(参数*a){
printf(“str:%s\n”,a->str);
}
#定义foo(…)包装器(&(参数){.function=foo,_VA_ARGS__})
#定义条(…)包装(&(参数){.function=bar,.str=“”,uu VA_ARGS_uu})
内部主(空){
foo(.x=42,.y=11);
酒吧(.str=“hello world”);
}
实际上,这种包装方式有一些非常好的特性:
- 下游编程人员很难使用堆栈,因为程序员很容易使用典型的可变函数,例如
和printf
,通过向这些函数传递错误的类型和/或值,导致微妙但破坏性的错误。这引出我的下一点:scanf
- 只需修改
和foo
宏,就可以使用默认参数值。作为上面代码中的一个示例,名为bar
的参数的默认值被设置为str
(一个空字符串),用于”
bar
- 通过在
包装器中引入额外的逻辑,您可以模拟部分函数应用程序(或者将属性绑定到函数,就像在Javascript中看到的那样)。此外,只需稍加努力,就可以通过将
转换为蹦床式函数并修改返回值来模仿连续传递方式?我将对此进行更多思考,并在明天提供更新包装器
- 最后,鼓励下游用户将参数标识符与参数值配对,这大大提高了可维护性
foo
和bar
都不能作为参数传递给另一个函数。这对于这些函数来说是非常罕见的,因为它们在签名上有很大的不同,但是对于签名相同甚至相似的函数,我可以理解人们可能希望将它们作为回调传递,或者什么都不传递
解决这个问题的方法是将宏重命名为default\u foo
和default\u bar
或类似的东西
最后,谢谢你提出这样一个发人深省的问题。。。我希望阅读我的答案对你来说就像思考(和写作)它对我一样有趣。这是我能想到的变量函数的最佳选择:
#include <stdio.h>
#include <stdarg.h>
void wrapper(void (*func)(va_list), ...) {
va_list args;
va_start(args, func);
func(args);
va_end(args);
}
void foo(int x, int y)
{
printf("foo(%d,%d)\n", x, y);
}
void vfoo(va_list args)
{
foo(va_arg(args, int), va_arg(args, int));
}
void bar(char *z)
{
printf("bar(%s)\n", z);
}
void vbar(va_list args)
{
bar(va_arg(args, char*));
}
int main()
{
wrapper(vfoo, 1, 2);
wrapper(vbar, "Hello, World!");
return 0;
}
#包括
#包括
无效包装(无效(*func)(va_列表),…){
va_列表参数;
va_启动(参数、函数);
func(args);
va_端(args);
}
无效foo(整数x,整数y)
{
printf(“foo(%d,%d)\n”,x,y);
}
void vfoo(va_列表参数)
{
foo(va_arg(args,int),va_arg(args,int));
}
空栏(字符*z)
{
printf(“条(%s)\n”,z);
}
无效vbar(VAU列表参数)
{
bar(va_arg(args,char*);
}
int main()
{
包装器(vfoo,1,2);
包装器(vbar,“你好,世界!”);
返回0;
}
.你可以使用一个变量函数作为包装器。@ForceBru所以我需要在
包装器
中使用某种分支逻辑来区分foo
和bar
?另一方面,如果你想从Javascript中获得一个特性,你可能应该用Javascript编写你的代码……不确定我是否同意你的观点。我想从Javascript/Python/等中获得很多功能,但鉴于我正在编写一个基本的操作系统,我认为这是不可能的。酷-我想你不需要包装器中的任何逻辑。\define
需要parentheses@ringø你指的是哪个#定义?那么第一个呢?我认为你错了。OP明确地希望能够调用包装器
中具有不同签名的函数,例如:包装器(foo(42,11));包装(酒吧(“你好世界”)代码>…我确实弄错了;-)@先生周四在考虑了您的需求一段时间后,我得出结论,当我建议使用Javascript(在评论中)时,我错了。请看我的编辑;希望你能找到s