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);//可以获取对端的数据,比如状态或者其他
}
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 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;
}