- 论坛徽章:
- 2
|
本帖最后由 OwnWaterloo 于 2011-11-30 19:29 编辑
回复 8# zylthinking
不搜出那帖这事我都忘了…… 过程也不记得了……
输赢什么的是小事。 只要弄清楚这东西是干什么的, 什么场合该用明白人自然清楚。
反正我是没敢在任何实际代码中用这东西, 即使opencv真的搞的人抓耳挠腮也没敢用……
问题是这样的, 有些legacy code对回调的函数的签名设计不好, 例子很多: qsort/bsearch, signal_handler(libc), WndProc(Windows GUI), opencv也有。
f 将 callback 传递给 g, 之后 callback 可能在某些时刻被调用。
当它被调用的时候, 能够获取的信息包括它在某个不知道的地方被调用时传递的参数, 或者某些全局的东西, 静态变量/线程局部变量等……
一般来说, 完备 的签名是 return_type callback(void* context, params...) 。 g( ... , callback, void* context );
如果某个 Acallback 需要 params... 之外的信息, 就可以让f给g传递一个context参数, Acallback被调用时获取。
如果某个 Bcallback 不需要, 那就让它空着。
一个void* 参数就够了, 因为可以塞个什么结构体的地址进去……
但完全没有这个参数就是不完备的。 如果某个Ccallback 需要这样的信息时, 就很麻烦了……
上面说的是一般情况。
也存在一些案例, void* context 参数是隐式的。 如果需要可以通过另一个参数传递。
也存在一些案例, 没有这样的参数,无论是隐式或显式, 但需要时也能解决问题。
比如(那个原帖我忘是啥了……) 就说这个帖, 给qsort传递。 因为对qsort返回后肯定不会再使用cmp, 所以直接一个静态变量(或者多线程下线程局部)就够用了。
这就是没有context参数也能解决问题的案例。
但有些时候就不行, 比如opencv, 只能将callback当作一个通知, 然后遍历全部窗口让它们更新 —— 但其实只有一种一个是真正需要更新。
它就属于 g(callback, args...) callback调用时期不确定的那一类。
而我想做的是一种一般化(当然目前是限定在i386下)的解法。 无论具体问题是什么, 只要是这一类问题就可以使用。
这种机制叫parital application。
一些社区将函数调用(invoke/call) 叫做应用(apply) , apply(f, a, b c) 以 a b c 3个参数调用f 。
部分应用就是只给出一部分参数, g = partial_apply(f, a) 。
得到的g是另一个函数, 可以继续部分应用或者全部应用 apply(g, b, c) 等效于 apply(f, a, b, c) 。
多个被部分应用的结果函数相互之间不会有干扰, 也可以同时存在。
如果在C里面实现了partial application的机制, 对这种缺少参数的问题只要先将那个缺少的参数部分应用, 并将返回的函数传递给需要callback的地方即可。
当callback真正被调用时会提供余下的参数。
嗯, 这些也只是理论上的搞搞。 实践上没这个胆子用…… |
|