为了避免在运行时取决于库,我编写了一个动态加载程序,该加载程序使用 dlopen
/ dlsym
在运行时形成库。
要在构建时间链接,我使用包装函数,这些功能将 dlsym
设置的功能指针调用。
我遇到了variadic函数的问题,那里似乎没有一种动态加载功能并将其转发为变异参数的方法。
有没有办法编写支持不支持varargs的包装库……
- 取决于知道variadic参数的数量或以哨兵值结束参数。
- 通过更改调用variadic函数的代码(在这种情况下我无法控制)来依赖于解决问题的工作。
似乎可以支持这一点,但是大多数现有的答案都表明,在我的用例中,以不实际的方式解决问题。
对于上下文,我包装的功能签名是:
struct wl_proxy *wl_proxy_marshal_flags(
struct wl_proxy *proxy,
uint32_t opcode,
const struct wl_interface *interface,
uint32_t version,
uint32_t flags,
...);
此功能通过生成的代码调用(请参阅 Wayland-Scanner
),尽管我宁愿不专门提出这个问题。
请注意,已经提出了类似的问题,例如:
,但他们建议在我的用例中使用 vfprintf
诸如使用 vfprintf
。
In order to avoid depending on a library at run-time I have written a dynamic loader that uses dlopen
/ dlsym
to load functions form a library at run-time.
To link at build time I use wrapper functions which call into the function pointers set by dlsym
.
I've run into a problem with variadic functions, where there doesn't seem to be a way to dynamically load the function and have it forward the variadic arguments.
Is there a way to write a wrapper library that supports varargs that doesn't...
- Depend on knowing the number of variadic arguments or ending the arguments with a sentinel value.
- Depend on working around the problem by changing the code which calls into the variadic function (which I happen not to have control over in this case).
It seems like this might be supported but most existing answers suggest to workaround the problem in a way that isn't practical in my use case.
For context the function signature I'm wrapping is:
struct wl_proxy *wl_proxy_marshal_flags(
struct wl_proxy *proxy,
uint32_t opcode,
const struct wl_interface *interface,
uint32_t version,
uint32_t flags,
...);
This function is called by generated code (see wayland-scanner
), although I rather not make this question specifically about Wayland.
Note that similar questions have been asked already, such as:
But they suggest alternatives such as using vfprintf
which don't work in my use case.
发布评论
评论(3)
通常的方法是使variadic函数仅在真实函数上以
va_list
作为参数作为界面。此模式(这是fprintf
和vfprintf
在标准库中工作的方式),通过使用va_list 。
在这里您可以写:
The usual way is to make the variadic function a mere interface on a real function taking a
va_list
as a parameter. This pattern (which is the wayfprintf
andvfprintf
work in the Standard Library) provides a smooth way to forward a dynamic number of arguments by calling directly the function using theva_list
.Here you could write:
假设variadic参数列表中的所有项目均为相同的类型,那么您可以使用此技巧:
将实际函数实现为非variadic的函数,占据数组和大小。以及任意数量的非广播论点。示例:
此处
可以是任何类型的任何参数,与示例中的固定参数相对应。
此
和argc
和argv
分别是大小和数组。然后,我们可以编写一个variadic宏来将variadic调用转换为一个普通函数调用:
辅助宏
count_args
计算variadic项目的数量 - 它们都必须是int
或它行不通。这给出了数组大小。然后,以变色的参数初始化了以复合文字形式的临时数组,然后传递给该函数。完整的示例:这与整数分配具有相同的类型安全性,含义是SO-SO,但它比Variadic函数更安全。
Assuming all items in the variadic argument list are of the same type, then you can use this trick:
Implement the actual function as a non-variadic one, taking an array and size. As well as any number of non-variadic arguments. Example:
Here
this
andthat
can be any parameters of any type, corresponding to the fixed parameters in your examples. Theargc
andargv
is the size and array respectively.We can then write a variadic macro to translate the variadic call into a plain function call:
The helper macro
COUNT_ARGS
counts the number of variadic items - they all have to beint
or it won't work. This gives the array size. Then a temporary array in the form of a compound literal is initialized with the variadic arguments, then passed to the function. Full example:This has the same type safety as integer assignment, meaning so-so, but it is way safer than variadic functions.
坏消息:我认为没有一个通用(与平台无关的)解决方案。
好消息:Wayland的开发人员似乎已经想到了这个问题,这就是为什么他们创建了
_array _
函数,例如Wayland-client-core.h
:以前的函数调用后者的函数:
Bad news: I don't think there is an universal (platform-independent) solution.
Good news: Wayland's developers seem to have thought of this problem, that's why they created
_array_
functions, e.g. inwayland-client-core.h
:The former function calls the latter: