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, stringconst char * psz);//只输入,不带返回值

int Add(inint a1,inint a2);//带返回值

int GetTestString(outPMYSTRING *pName);//可以获取对端的数据,比如状态或者其他

}

ACF文件如下内容

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 charret + 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、运行结果
相关推荐
码客-ygluu7 小时前
X3 LUA 异步分布式微服务集群框架
c++·架构·lua
九英里路10 小时前
protobuf快速上手
网络·c++·中间件·json·谷歌·序列化·protobuf
纪念 22911 小时前
C++ 算法基础 (差分)
开发语言·c++·算法
ShineWinsu16 小时前
对于Qt:QTreeWidget常见属性以及QTreeWidgetItem类的解析
开发语言·c++·qt·gui·客户端·多叉树·qtreewidget
落羽的落羽16 小时前
【C++】C++17的主要特性
linux·服务器·开发语言·c++·算法·机器学习
Funlang18 小时前
在 Windows 95 上跑 Fun
windows
汉克老师1 天前
《从C++小白到算法高手:GESP 1—8级成长地图》第一讲:认识GESP——从编程新手到算法探索者
c++·gesp·信息学竞赛·小学生学c++
晴天的雨.9921 天前
【C++】继承篇
java·开发语言·c++
ö Constancy1 天前
一台电脑的硬件组成与作用:按功能分类详解(Windows 与 Linux 视角)
linux·windows·电脑
青少儿编程课堂1 天前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会图形化考级:校园大富翁经营闯关解析
c++·python·算法·bfs·信息学竞赛