客户端应用程序

以下示例来自平台软件开发工具包的 RPC\Hello 目录中的“Hello World”应用程序 (SDK) 。 Helloc.c 源文件包含包含 MIDL 生成的头文件 Hello.h 的指令。 在 Hello.h 中是包含 Rpc.h 和 rpcndr.h 的指令,其中包含 RPC 运行时例程、 HelloProcShutdown 的定义,以及客户端和服务器应用程序使用的数据类型。 MIDL 编译器必须与以下示例一起使用。

由于客户端正在管理其与服务器的连接,因此客户端应用程序调用运行时函数来建立服务器的句柄,并在远程过程调用完成后释放此句柄。 函数 RpcStringBindingCompose 将绑定句柄的组件合并到该句柄的字符串表示形式中,并为字符串绑定分配内存。 函数 RpcBindingFromStringBinding 从该字符串表示形式为客户端应用程序创建hello_ClientIfHandle服务器绑定句柄。

在调用 RpcStringBindingCompose 时,参数不会指定 UUID,因为本教程假定只有一个接口“hello”实现。此外,调用未指定网络地址,因为应用程序将使用默认值,即本地主机。 协议序列是表示基础网络传输的字符串。 终结点是特定于协议序列的名称。 此示例使用命名管道进行网络传输,因此协议序列为“ncacn_np”。 终结点名称为“\pipe\hello”。

实际的远程过程调用 HelloProcShutdown 发生在 RPC 异常处理程序中,这是一组宏,可用于控制应用程序代码外部发生的异常。 如果 RPC 运行时模块报告异常,则控件将传递给 RpcExcept 块。 在此位置,可以插入代码以执行任何所需的清理,然后正常退出。 此示例程序只是通知用户发生了异常。 如果不想使用异常,可以使用 ACF 属性 comm_statusfault_status 来报告错误。

远程过程调用完成后,客户端首先调用 RpcStringFree 以释放为字符串绑定分配的内存。 请注意,创建绑定句柄后,客户端程序可以随时释放字符串绑定。 客户端接下来调用 RpcBindingFree 以释放句柄。

/* file: helloc.c */
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "hello.h" 
#include <windows.h>

void main()
{
    RPC_STATUS status;
    unsigned char * pszUuid             = NULL;
    unsigned char * pszProtocolSequence = "ncacn_np";
    unsigned char * pszNetworkAddress   = NULL;
    unsigned char * pszEndpoint         = "\\pipe\\hello";
    unsigned char * pszOptions          = NULL;
    unsigned char * pszStringBinding    = NULL;
    unsigned char * pszString           = "hello, world";
    unsigned long ulCode;
 
    status = RpcStringBindingCompose(pszUuid,
                                     pszProtocolSequence,
                                     pszNetworkAddress,
                                     pszEndpoint,
                                     pszOptions,
                                     &pszStringBinding);
    if (status) exit(status);

    status = RpcBindingFromStringBinding(pszStringBinding, &hello_ClientIfHandle);
 
    if (status) exit(status);
 
    RpcTryExcept  
    {
        HelloProc(pszString);
        Shutdown();
    }
    RpcExcept(1) 
    {
        ulCode = RpcExceptionCode();
        printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
    }
    RpcEndExcept
 
    status = RpcStringFree(&pszStringBinding); 
 
    if (status) exit(status);
 
    status = RpcBindingFree(&hello_IfHandle);
 
    if (status) exit(status);

    exit(0);
}

/******************************************************/
/*         MIDL allocate and free                     */
/******************************************************/
 
void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
{
    return(malloc(len));
}
 
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
    free(ptr);
}