我们可以看一段代码
ConnectWrap* req_wrap = new ConnectWrap(env, req_wrap_obj, ...);
req_wrap->Dispatch(uv_tcp_connect,
&wrap->handle_,
reinterpret_cast<const sockaddr*>(&addr),
AfterConnect);
这里调用了Dispatch是属于ReqWrap类的
template <typename T>
template <typename LibuvFunction, typename... Args>
int ReqWrap<T>::Dispatch(LibuvFunction fn, Args... args) {
Dispatched();
CallLibuvFunction<T, LibuvFunction>::Call(
fn,
env()->event_loop(),
req(),
MakeLibuvRequestCallback<T, Args>::For(this, args)...);
}
Dispatched是一个设置data,不用管,可以看到这里调用了 CallLibuvFunction<T, LibuvFunction>::Call
我们去看看看Call的代码
// Detect `int uv_foo(uv_loop_t* loop, uv_req_t* request, ...);`.
template <typename ReqT, typename... Args>
struct CallLibuvFunction<ReqT, int(*)(uv_loop_t*, ReqT*, Args...)> {
using T = int(*)(uv_loop_t*, ReqT*, Args...);
template <typename... PassedArgs>
static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) {
return fn(loop, req, args...);
}
};
// Detect `int uv_foo(uv_req_t* request, ...);`.
template <typename ReqT, typename... Args>
struct CallLibuvFunction<ReqT, int(*)(ReqT*, Args...)> {
using T = int(*)(ReqT*, Args...);
template <typename... PassedArgs>
static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) {
return fn(req, args...);
}
};
// Detect `void uv_foo(uv_req_t* request, ...);`.
template <typename ReqT, typename... Args>
struct CallLibuvFunction<ReqT, void(*)(ReqT*, Args...)> {
using T = void(*)(ReqT*, Args...);
template <typename... PassedArgs>
static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) {
fn(req, args...);
return 0;
}
};
因为我们调用的uv_tcp_connect的函数表达式是
int uv_tcp_connect(uv_connect_t req,
uv_tcp_t handle,
const struct sockaddr* addr,
uv_connect_cb cb)
所以应该执行的是
// Detect `int uv_foo(uv_req_t* request, ...);`.
template <typename ReqT, typename... Args>
struct CallLibuvFunction<ReqT, int(*)(ReqT*, Args...)> {
using T = int(*)(ReqT*, Args...);
template <typename... PassedArgs>
static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) {
return fn(req, args...);
}
};
所以我们调用的是
uv_tcp_connect(req(), MakeLibuvRequestCallback<T, Args>::For(this, args)...)
args收集是
template <typename LibuvFunction, typename... Args>
int ReqWrap<T>::Dispatch(LibuvFunction fn, Args... args)
也就是Dispatch除了fn的函数那就是
三个
我们拼接上得到了
uv_tcp_connect(req(), MakeLibuvRequestCallback<T, Args>::For(this, &wrap->handle_,
reinterpret_cast<const sockaddr*>(&addr),
AfterConnect)...)
现在我们看看MakeLibuvRequestCallback是什么
template <typename ReqT, typename T>
struct MakeLibuvRequestCallback {
static T For(ReqWrap<ReqT>* req_wrap, T v) {
return v;
}
};
template <typename ReqT, typename... Args>
struct MakeLibuvRequestCallback<ReqT, void(*)(ReqT*, Args...)> {
using F = void(*)(ReqT* req, Args... args);
static void Wrapper(ReqT* req, Args... args) {
ReqWrap<ReqT>* req_wrap = ReqWrap<ReqT>::from_req(req);
F original_callback = reinterpret_cast<F>(req_wrap->original_callback_);
original_callback(req, args...);
}
static F For(ReqWrap<ReqT>* req_wrap, F v) {
req_wrap->original_callback_ = reinterpret_cast<typename ReqWrap<ReqT>::callback_t>(v);
return Wrapper;
}
};
可以看到分为两种情况
如果传入的第二个参数不是函数,则将参数直接原封不动传出去,如果是函数,则进行包裹返回一个函数
我们这里第二个参数是&wrap->handle_
一个handle
所以会透传,那么最后
uv_tcp_connect(req(), MakeLibuvRequestCallback<T, Args>::For(this, &wrap->handle_,
reinterpret_cast<const sockaddr*>(&addr),
AfterConnect)...)
会变成
uv_tcp_connect(
req(),
&wrap->handle_,
reinterpret_cast<const sockaddr*>(&addr),
AfterConnect
)
刚好符合tcp的调用头
int uv_tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
const struct sockaddr* addr,
uv_connect_cb cb) {
// ...
return uv__tcp_connect(req, handle, addr, addrlen, cb);
}