Клиентское приложение
Приведенный ниже пример получен из приложения "Hello World" в каталоге RPC\Hello пакета средств разработки программного обеспечения платформы (SDK). Исходный файл Helloc.c содержит директиву для включения созданного MIDL файла заголовка Hello.h. В Hello.h находятся директивы для включения Rpc.h и rpcndr.h, которые содержат определения для подпрограмм времени выполнения RPC, HelloProc и Shutdown, а также типы данных, используемые клиентскими и серверными приложениями. Компилятор MIDL необходимо использовать в приведенном ниже примере.
Так как клиент управляет подключением к серверу, клиентское приложение вызывает функции времени выполнения, чтобы установить дескриптор для сервера и освободить этот дескриптор после завершения вызовов удаленных процедур. Функция RpcStringBindingCompose объединяет компоненты дескриптора привязки в строковое представление этого дескриптора и выделяет память для привязки строки. Функция RpcBindingFromStringBinding создает дескриптор привязки сервера , hello_ClientIfHandle, для клиентского приложения из этого строкового представления.
В вызове RpcStringBindingCompose параметры не указывают UUID, так как в этом руководстве предполагается, что существует только одна реализация интерфейса hello. Кроме того, в вызове не указан сетевой адрес, так как приложение будет использовать значение по умолчанию, которое является локальным хост-компьютером. Последовательность протокола — это строка символов, представляющая базовый сетевой транспорт. Конечная точка — это имя, которое зависит от последовательности протокола. В этом примере для сетевого транспорта используются именованные каналы, поэтому последовательность протокола — "ncacn_np". Имя конечной точки — \pipe\hello.
Фактические удаленные вызовы процедур HelloProc и Shutdown выполняются в обработчике исключений RPC — наборе макросов, которые позволяют управлять исключениями, происходящими за пределами кода приложения. Если модуль среды выполнения RPC сообщает об исключении, управление передается блоку RpcExcept . Здесь можно вставить код для выполнения любой необходимой очистки, а затем корректно завершить работу. Этот пример программы просто информирует пользователя о том, что произошло исключение. Если вы не хотите использовать исключения, можно использовать атрибуты ACF comm_status и fault_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);
}