Windows C++ 使用WinAPI实现RPC

demo下载地址:https://download.csdn.net/download/2403_83063732/88958730
1、创建IDL文件以及acf文件(创建helloworld.idl helloworld.acf)

其中IDL文件:

import "oaidl.idl";

import "ocidl.idl";

uuid("4556509F-618A-46CF-AB3D-ED736ED66477"), // 唯一的UUID,主要是用来通讯的时候使用 version(1.0)

interface HelloWorld

{

// 官方文档推荐的自定义字符串写法(带长度和大小)

typedef struct _MYSTRING

{

unsigned short size;

unsigned short length;

ptr,size_is(size), length_is(length)\] char string\[\*\]; } MYSTRING; typedef \[ptr\] MYSTRING\*\* PPMYSTRING; typedef \[ptr\] MYSTRING\* PMYSTRING; // 我们定义的方法,只列举这几个应该够我们用了 void Hello(\[in, string\]const char \* psz);//只输入,不带返回值 int Add(\[in\]int a1,\[in\]int a2);//带返回值 int GetTestString(\[out\]PMYSTRING \*pName);//可以获取对端的数据,比如状态或者其他 }

implicit_handle (handle_t HelloWorld_IfHandle)

interface HelloWorld

{

}

2、调用midl指令,生成.c/.h文件

midl helloworld.idl /acf helloworld.acf /out ./

如下生成helloworld.h ,helloworld_c.h,helloworld_s.h

3、创建客户端工程以及服务端工程

客户端工程包含helloworld.h ,helloworld_c.h

服务端工程包含helloworld.h ,helloworld_s.h

如下图

4、服务端代码

midl_user_allocate/midl_user_free函数必须要,不然编译会报错

#include "../TestRpcC/helloworld.h"

#pragma comment(lib,"Rpcrt4.lib")

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);

}

void Hello( const unsigned char * psz)

{

printf("Hello:%s\n", psz);

}

int Add(

/* [in] */ int a1,

/* [in] */ int a2)

{

return a1 + a2;

}

int GetTestString(

/* [out] */ PMYSTRING *pName)

{

int nLen = strlen("test");

*pName = (PMYSTRING)MIDL_user_allocate(sizeof(PMYSTRING) + nLen);

(*pName)->length = nLen;

(*pName)->size = sizeof(PMYSTRING) + nLen;

strncpy((char*)(*pName)->string, "test", nLen);

return nLen;

}

int main()

{

// 用Named Pipe 作为RPC 的通道,这样EndPoint 参数就是Named Pipe 的名字

// 按照Named Pipe 的命名规范,/pipe/pipename,其中pipename 可以是除了/

// 之外的任意字符,那么这里用一个GUID 串来命名,可以保证不会重复

RPC_STATUS st = RpcServerUseProtseqEpA((unsigned char *)"ncacn_np", 20, (unsigned char *)"\\pipe\\{8dd50205-3108-498f-96e8-dbc4ec074cf9}", NULL);

if (st != RPC_S_OK)

{

return -1;

}

// 注册接口,HelloWorld_v1_0_s_ifspec 是在MIDL 生成的helloworld.h 中定义的

st = RpcServerRegisterIf(HelloWorld_v1_0_s_ifspec, NULL, NULL);

if (st != RPC_S_OK)

{

return -1;

}

// 开始监听,本函数将一直阻塞

st = RpcServerListen(1, 20, FALSE);

if (st != RPC_S_OK)

{

return -1;

}

return 0;

}

5、客户端代码

midl_user_allocate/midl_user_free函数必须要,不然编译会报错

#include "helloworld.h"

#pragma comment(lib,"Rpcrt4.lib")

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);

}

int main()

{

unsigned char *pszUuid = NULL;

unsigned char pszProtocolSequence[] = "ncacn_np";

unsigned char *pszNetworkAddress = NULL;

unsigned char pszEndpoint[] = "\\pipe\\{8dd50205-3108-498f-96e8-dbc4ec074cf9}";

unsigned char *pszOptions = NULL;

unsigned char *pszStringBinding = NULL;

RPC_STATUS rpcStatus = RpcStringBindingComposeA(pszUuid,

pszProtocolSequence,

pszNetworkAddress,

pszEndpoint,

pszOptions,&pszStringBinding);

if (rpcStatus)

exit(rpcStatus);

rpcStatus = RpcBindingFromStringBindingA(pszStringBinding,&HelloWorld_IfHandle);

if (rpcStatus)

exit(rpcStatus);

RpcTryExcept

{

Hello((unsigned char *)"nihaosadjklasjldkjaskldjkasdasdasdasdasdasdasdasd");

int ret = Add(16, 40);

printf("ret = %d \n", ret);

PMYSTRING baseData = NULL;

ret = GetTestString(&baseData);

if (ret > 0)

{

char *pBuf = new char[ret + 1];

memset(pBuf,0,ret + 1);

memcpy(pBuf, baseData->string,ret);

printf("ret = {%d,%s} \n", ret, pBuf);

delete[]pBuf;

}

}

RpcExcept(1)

{

unsigned long ulCode = RpcExceptionCode();

printf("抛出异常0x%lx = %ld。\n", ulCode, ulCode);

}

RpcEndExcept

rpcStatus = RpcStringFreeA(&pszStringBinding);

if (rpcStatus)

exit(rpcStatus);

rpcStatus = RpcBindingFree(&HelloWorld_IfHandle);

if (rpcStatus)

exit(rpcStatus);

return 0;

}

6、运行结果
相关推荐
坚定学代码2 分钟前
认识 ‘using namespace‘
c++
jiang_changsheng7 分钟前
环境管理工具全景图与深度对比
java·c语言·开发语言·c++·python·r语言
yaoxin52112312 分钟前
314. Java Stream API - 使用 Collectors.partitioningBy() 分区元素
java·windows
LYOBOYI12313 分钟前
qml的对象树机制
c++·qt
LeoZY_20 分钟前
开源项目精选:Dear ImGui —— 轻量高效的 C++ 即时模式 GUI 框架
开发语言·c++·ui·开源·开源软件
特立独行的猫a1 小时前
C++轻量级Web框架介绍与对比:Crow与httplib
开发语言·前端·c++·crow·httplib
云小逸1 小时前
【windows核心编程】Windows GDI编程深度解析:从消息循环到双缓冲动画的完整实现
windows
YXXY3131 小时前
模拟实现map和set
c++
阿猿收手吧!1 小时前
【C++】引用类型全解析:左值、右值与万能引用
开发语言·c++
「QT(C++)开发工程师」1 小时前
C++ 策略模式
开发语言·c++·策略模式