这个可变参数列表函数调用是如何工作的?

Posted

技术标签:

【中文标题】这个可变参数列表函数调用是如何工作的?【英文标题】:How does this variable parameters list function call works? 【发布时间】:2011-08-18 07:20:33 【问题描述】:

当程序需要使用 Microsoft RPC 进行通信时,开发人员通常会为所有方法编写 IDL 定义,例如:

error_status_t rpcMyInterfaceGetFile( [in] const GUID fileId, [out] BYTE_PIPE filePipe );

由 MIDL 编译器编译并产生一个包装函数:

/* [fault_status][comm_status] */ error_status_t rpcMyInterfacerGetFile( 
/* [in] */ handle_t IDL_handle,
/* [in] */ const GUID fileId,
/* [out] */ BYTE_PIPE filePipe)

    CLIENT_CALL_RETURN _RetVal;
    _RetVal = NdrClientCall2(
              ( PMIDL_STUB_DESC  )&IMyInterfaceRpc_StubDesc,
              (PFORMAT_STRING) &MyInterfaceRpc__MIDL_ProcFormatString.Format[SomeNumberHere],
              ( unsigned char * )&IDL_handle);
    return ( error_status_t  )_RetVal.Simple;

这里调用被转发到NdrClientCall2() RPC runtime function,它被声明为将... 作为第三个参数并执行实际工作。 MyInterfaceRpc__MIDL_ProcFormatString 只是 MIDL 生成的硬编码字节序列,因此第二个参数是该数组中的一个小节的开头,该数组在与包装函数相同的 .c 文件中声明并具有静态存储持续时间。

参数(fileIdfilePipe)如何传递到NdrClientCall2()?我没有看到他们被通过。它们是如何从包装器中获取到NdrClientCall2() 的?

【问题讨论】:

【参考方案1】:

嗯,不太确定,但在 MSDN doc 的行之间读取(这表示最后一个参数是 指向客户端调用堆栈的指针)听起来像 NdrClientCall2 函数可以采用 STUB_DESC 结构,找出参数类型和大小,从堆栈中提取它们,完成调用远程接口的工作,然后将结果写回堆栈上的正确位置(用于 OUT 参数)。

【讨论】:

【参考方案2】:

无需深入研究,在我看来,通过传递堆栈上第一个参数的地址(&IDL_handle),NdrClientCall2 的实现可以看到也在堆栈上的后续参数。 NdrClientCall2 的第二个参数表示可变参数的数量和大小。

【讨论】:

以上是关于这个可变参数列表函数调用是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

可变参数列表

在Javascript中的可变参数函数内调用可变参数函数?

c语言可变参数是干啥的

如何使用可变参数模板参数保存可变数量的参数?

如何在所有可变参数模板参数上调用函数?

go语言学习笔记 — 基础 — 函数:可变参数