【发布时间】:2019-01-08 14:49:57
【问题描述】:
我必须对以下格式的可变参数函数执行动态链接:
int foo(char *args, const char *f, ...)
这里参数的数量是可变的。 我想要实现的是我想将获得的参数传递给我正在使用 dlsym 解析的原始函数。 如果我不传递所有参数,我会不断遇到分段错误。 提前致谢。
【问题讨论】:
标签: c variadic-functions dynamic-linking ld-preload dlsym
我必须对以下格式的可变参数函数执行动态链接:
int foo(char *args, const char *f, ...)
这里参数的数量是可变的。 我想要实现的是我想将获得的参数传递给我正在使用 dlsym 解析的原始函数。 如果我不传递所有参数,我会不断遇到分段错误。 提前致谢。
【问题讨论】:
标签: c variadic-functions dynamic-linking ld-preload dlsym
我认为您的问题与 LD_PRELOAD 或 dlopen/dlsym 无关:您只是想从可变参数函数中调用可变参数函数,例如:
int printf (const char *fmt, ...) {
return fprintf (stdout, fmt, my_variadic_parameters);
}
据我所知,这是不可能的,但是在精心设计的库中(这显然是少数),每个可变参数函数都有一个使用va_list 参数的对应项,如 printf 和 vprintf、fprintf 和 vfprintf :
int printf (const char *fmt, ...) {
va_list ap;
int retval;
va_start (ap, fmt);
retval= vfprintf (stdout, fmt, ap);
va_end (ap);
return retval;
}
int vmyprintf (const char *fmt, va_list pap) {
va_list ap;
int retval;
va_copy (ap, pap);
retval= vfprintf (stdout, fmt, ap);
va_end (ap);
return retval;
}
所以你应该要求'foo'的创建者创建一个'vfoo':
int vfoo (char *args, const char *f, va_list v)
【讨论】:
查看man va_start,该手册页中有一个非常简洁的示例。
您可以像对待任何其他函数指针一样对待 dlsym 符号地址。
va_args 背后的基本概念是在循环中使用控制变量,通常是printf 样式的格式字符串,可以对其进行解析以决定何时退出调用帧构建循环。在您的情况下 ankit,您需要在构建va_list 时采用某种形式“在调用框架中放置另一个参数”。基本上是 va_start va_arg... va_end。
再一次,最好用代码解释,手册页有一个很好的例子。
【讨论】:
va_arg 函数希望您知道从va_list 中提取哪些类型。
给定
int foo(char *args, const char *f, ...)
args 或f 提供的信息应该告诉您调用者已将多少个类型的参数作为可变参数传递。
如何提供此信息取决于foo 的实现,因此请参阅foo() 文档。
一个很好的例子是printf(const char * format, ...); 作为可变参数接收到的所有信息都可以从第一个参数中解析,即非可变格式-“字符串”。
如果你无法深入了解这一点,你就会迷失方向。在 C 中,没有通用的“内置”方式来收集传递的可变参数的数量和类型。
【讨论】:
va_arg 的连续调用从va_list 中提取值,这是对va_start 的初始调用给你的。