protobuf通过串口实现函数方法远程调用并相互回调,不使用gRPC(串口原因)

需求:

现在有函数A、B,分别在两个设备上,通过串口连接。函数返回值都有多个,含字节数组。

问题:

1.protobuf只是序列化,并没有通信协议。串口无法判断发送结束及校验等。

方法:比如加个类似modbus协议:头,数据长度,数据,校验。

2.设备1发送函数名及参数后就阻塞,等返回值。如果设备2也同时同样的操作(回调函数),同时发送,怎么分辨是返回值还是回调函数?

方法:发送返回值不需要带函数名,即没函数名是返回值。你只能用已知的类去解析它,返回值你知道解析它的类。但回调函数没法知道?所有请求都加上函数名呢?可以。

3.回调函数没法知道解析它的类,可以先只取函数名吗?

方法:可以只取函数名,类中必须要有这个字段,没有会报错。没有赋值为空,不报错。可以实现回调函数。

验证代码:不同的Message,位置与类型相同是可以解析的。

4.解析有默认值,会有岐义。不能区分是真正的值,还是没解析到的默认值?

方法:在所有的Message里加个int32 messageType=1,当为0时错误,1时为函数调用,2时为返回值。OK非常好用。

网上很多错误又复杂的做法!!!比如加个基数,oneof等解决不了。比如默认返回为0,我加基数10,值不能小于10,没解析到的默认值为0,解析时是按第一个值是多少,不同字段名但值是相同的。

约定:
1.所有消息增加消息类型  int32 messageType = 1;,值定义:0错误(默认值,不使用) 1函数调用 2返回值。
2.所有函数增加函数索引  int32 methodIndex = 2;。
3.所有返回值字段名用returnValue
4.byte数组 都转成十六进制字符串,收发都转。好处理些。但所有长度是指针的,直接用整型传值。
5.结构体像单独字段一样传,顺序不变。

demo::People p;
	p.set_id(123);
	p.set_name( "chenhao");
	p.set_email("11@qq.com");
	string data;
	p.SerializeToString(&data);

demo::People2 pNew;
	pNew.ParseFromString(data);
	cout << "NewPeople: " << endl;
	cout << "Name: " << pNew.name() << endl;

5.用  bool SerializeToArray(void* data, int size),没有直接提供输出长度,奇葩不?

方法:用这个得到输出长度ByteSizeLong()

好,所有问题都解决了。

流程:

设备1发送函数名及参数后就阻塞,等返回值。设备2根据函数名,调用函数执行,返回函数名及返回值。设备1收到后回到阻塞位置继续执行。

A发送函数调用请求逻辑(C++):

1.函数名

2.封装request

3.串口发送

4.阻塞等待接收标志

5.解析reply 到函数输出

6.返回值

A接收函数调用逻辑 即回调函数(C++):

1.收到函数调用请求(非返回值)

2.解析request到接口函数

3.接口函数执行

4.发送返回值

 B调用与回调函数逻辑(C++): 同上A。

A与B功能一样,互为client与server,可相互调用。接收是单独的线程,即回调函数是在线程中调用的。

A示例代码(C++)

// ConsoleApplicationProtobuf.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include "people.proto3.pb.h"
#include "D:\009protobuff\grpc-java-1.42.0\test2\pos.pb.h"
#include "./windows/commSever.h"
#include "./windows/comm_protocol.h"
#pragma comment(lib, "libprotobufd.lib")
using namespace std;

//约定:1.所有函数有函数索引,有DWORD返回值。并加上基数。
//2.byte数组 都转成十六进制字符串,收发都转。好处理些。但有些长度是指针的,直接用整型传值。
//3.结构体像单独字段一样传。
CommSever comm;
#define Head0 0xAA
#define Head1 0x55
bool status;
byte recvBuffer[2048];
int recvBufferLength;
#define RECV_TIMEOUT 10 
#define RPC_FAILED  9999
#define RPC_TIMEOUT 9998
#define MESSAGE_TYPE_ERROR  0
#define MESSAGE_TYPE_METHOD 1
#define MESSAGE_TYPE_RETURN 2

void printfHexBytes(char *memo, byte* data, int dataLength)
{
	printf("%s(%d):", memo, dataLength);
	for (int i = 0; i < dataLength; i++)
		printf("%02X ", (int)data[i]);
	printf("\n");
}
//将字符串编码成16进制数字,适用于所有字符(包括中文)
std::string encodeHexString(const std::string& str) {
	// 根据默认编码获取字节数组
	const std::string hexString = "0123456789abcdef";
	string sb;
	// 将字节数组中每个字节拆解成2位16进制整数
	for (int i = 0; i < str.length(); i++) {
		sb += hexString.at((str[i] & 0xf0) >> 4);
		sb += hexString.at((str[i] & 0x0f) >> 0);
	}
	return sb;
}
//16进制字符串转字符串
std::string hexStringToString(const std::string& hexStr)
{
	std::string ret;
	const std::string hexString = "0123456789abcdef";
	// 将每2位16进制整数组装成一个字节
	for (int i = 0; i < hexStr.length(); i += 2)
		ret += BYTE(hexString.find(hexStr.at(i)) << 4 | hexString.find(hexStr.at(i + 1)));
	return ret;
}
//字节数组转16进制字符串
std::string bytesToHexString(const BYTE* bytes, const int length)
{
	if (bytes == NULL) {
		return "";
	}
	std::string buff;
	const int len = length;
	for (int j = 0; j < len; j++) {
		int high = bytes[j] / 16, low = bytes[j] % 16;
		buff += (high < 10) ? ('0' + high) : ('a' + high - 10);
		buff += (low < 10) ? ('0' + low) : ('a' + low - 10);
	}
	return buff;
}
//16进制字符串 转 字节数组
void hexStringToBytes(const std::string& hex, BYTE* bytes)
{
	int bytelen = hex.length() / 2;
	std::string strByte;
	unsigned int n;
	for (int i = 0; i < bytelen; i++)
	{
		strByte = hex.substr(i * 2, 2);
		sscanf_s(strByte.c_str(), "%x", &n);
		bytes[i] = n;
	}
}


static BYTE crcLRC(BYTE * pbData, WORD wdataLen)
{
	BYTE bRet = 0;

	while (wdataLen--)
	{
		bRet ^= *pbData++;
	}

	return bRet;
}
int Send_Protocol(LPBYTE lpData, UINT nSize)
{
	BYTE sendData[2048];
	sendData[0] = Head0;
	sendData[1] = Head1;
	int length = nSize + 7;
	sendData[2] = (BYTE)(nSize >> 24);//length
	sendData[3] = (BYTE)(nSize >> 16);
	sendData[4] = (BYTE)(nSize >> 8);
	sendData[5] = (BYTE)(nSize);
	memcpy(sendData + 6, lpData, nSize);
	sendData[length - 1] = (BYTE)(crcLRC(lpData, nSize)); //crch
	return comm.Send(sendData, length);
}

int send_recv(string request, int timeout)
{
	status = false;
	Send_Protocol((byte *)request.data(), request.length());
	//等待直到超时或有返回值
	for (int i = 0; i < timeout * 1000; i++)
	{
		if (status)
		{
			return 0;
		}
		Sleep(1);//ms
	}
	std::cout << "RPC_TIMEOUT" << std::endl;
	return RPC_TIMEOUT;
}







using pos::InitializeRequest;
using pos::InitializeReply;
using pos::FinalizeRequest;
using pos::FinalizeReply;
using pos::SetKeyGroupNameRequest;
using pos::SetKeyGroupNameReply;
using pos::LoadDukptIpekRequest;
using pos::LoadDukptIpekReply;
using pos::LoadSymKeyRequest;
using pos::LoadSymKeyReply;
using pos::GetKSNRequest;
using pos::GetKSNReply;
using pos::IncreaseKSNRequest;
using pos::IncreaseKSNReply;
using pos::LoadTr31KeyByIndexRequest;
using pos::LoadTr31KeyByIndexReply;
using pos::ExchangeKeyWithECDHRequest;
using pos::ExchangeKeyWithECDHReply;
using pos::MacByIndexRequest;
using pos::MacByIndexReply;
using pos::ManagerCertFileRequest;
using pos::ManagerCertFileReply;
using pos::getCertFileRequest;
using pos::getCertFileReply;
using pos::SetAcquirerDataRequest;
using pos::SetAcquirerDataReply;
using pos::AddAppParametersRequest;
using pos::AddAppParametersReply;
using pos::DeleteAppParametersRequest;
using pos::DeleteAppParametersReply;
using pos::DeleteAllAppParametersRequest;
using pos::DeleteAllAppParametersReply;
using pos::AddDRLRequest;
using pos::AddDRLReply;
using pos::DeleteDRLRequest;
using pos::DeleteDRLReply;
using pos::DeleteAllDRLRequest;
using pos::DeleteAllDRLReply;
using pos::AddCAPubKeyRequest;
using pos::AddCAPubKeyReply;
using pos::DeleteCAPubKeyRequest;
using pos::DeleteCAPubKeyReply;
using pos::AddPRMacqRequest;
using pos::AddPRMacqReply;
using pos::SetICSRequest;
using pos::SetICSReply;
using pos::SetInteractionPointRequest;
using pos::SetInteractionPointReply;
using pos::StartTransactionRequest;
using pos::StartTransactionReply;
using pos::ContinueTransactionRequest;
using pos::ContinueTransactionReply;
using pos::GetTlvListRequest;
using pos::GetTlvListReply;
using pos::GetEncryptedDataElementRequest;
using pos::GetEncryptedDataElementReply;
using pos::GetMsDataRequest;
using pos::GetMsDataReply;
using pos::GetVersionRequest;
using pos::GetVersionReply;
using pos::GetDeviceInfoRequest;
using pos::GetDeviceInfoReply;
using pos::UpdatePosFileRequest;
using pos::UpdatePosFileReply;

DWORD GetDeviceInfo(OUT BYTE *pbInfo, IN OUT DWORD *pdwInfoLen, IN BYTE bFlag) {
	// Data we are sending to the server.
	std::cout << "invoke GetDeviceInfo" << std::endl;
	GetDeviceInfoRequest request;
	request.set_messagetype(1);
	request.set_methodindex(0);
	request.set_pdwinfolen(*pdwInfoLen);
	request.set_bflag(bFlag);
	// Container for the data we expect from the server.
	GetDeviceInfoReply reply;

	// Context for the client. It could be used to convey extra information to
	// the server and/or tweak certain RPC behaviors.

	// The actual RPC.
	string requestData;
	request.SerializeToString(&requestData);
	send_recv(requestData, RECV_TIMEOUT);

	// Act upon its status.
	if (status) {
		GetDeviceInfoReply reply;
		reply.ParseFromArray(recvBuffer, recvBufferLength);
		std::cout << "returnValue=" << reply.returnvalue() << std::endl;
		hexStringToBytes(reply.pbinfo(), pbInfo);
		std::cout << "pbInfo=" << reply.pbinfo() << std::endl;
		*pdwInfoLen = reply.pdwinfolen();
		std::cout << "pdwInfoLen=" << reply.pdwinfolen() << std::endl;
		return reply.returnvalue();
	}
	else {
		std::cout << "GetDeviceInfo" << " RPC_FAILED" << std::endl;
		return RPC_FAILED;
	}
}
//DWORD LoadSymKey(IN BYTE bKeyType, IN WORD wKeyIndex, IN BYTE bAlg, IN BYTE bProtectKeyType, IN WORD wProtectKeyIndex, IN BYTE *pbKeyData, IN WORD wKeyDataLen, IN OUT BYTE *pbKCV, IN BYTE bKCVLen, IN BYTE bKCVMode) {
//	// Data we are sending to the server.
//	LoadSymKeyRequest request;
//	request.set_methodindex(1);
//	request.set_bkeytype(bKeyType);
//	request.set_wkeyindex(wKeyIndex);
//	request.set_balg(bAlg);
//	request.set_bprotectkeytype(bProtectKeyType);
//	request.set_wprotectkeyindex(wProtectKeyIndex);
//	request.set_pbkeydata(bytesToHexString(pbKeyData, wKeyDataLen));
//	request.set_wkeydatalen(wKeyDataLen);
//	request.set_pbkcv(bytesToHexString(pbKCV, bKCVLen));
//	request.set_bkcvlen(bKCVLen);
//	request.set_bkcvmode(bKCVMode);
//
//	// Container for the data we expect from the server.
//
//	// The actual RPC.
//	string requestData;
//	request.SerializeToString(&requestData);
//	send_recv(requestData, RECV_TIMEOUT);
//	// Act upon its status.
//	if (status) {
//		LoadSymKeyReply reply;
//		reply.ParseFromArray(recvBuffer, recvBufferLength);
//		std::cout << "returnValue=" << reply.returnvalue() << std::endl;
//		hexStringToBytes(reply.pbkcv(), pbKCV);
//		std::cout << "pbKCV=" << reply.pbkcv() << std::endl;
//		return reply.returnvalue();
//	}
//	else {
//		std::cout << "LoadSymKey" << " RPC_FAILED" << std::endl;
//		return RPC_FAILED;
//	}
//}


回调的实际接口  
//DWORD GetDeviceInfoActualCallBack(OUT BYTE *pbInfo, IN OUT DWORD *pdwInfoLen, IN BYTE bFlag)
//{
//	std::cout << "pdwInfoLen=" << *pdwInfoLen << std::endl;
//	std::cout << "bFlag=" << bFlag << std::endl;
//
//	unsigned char data[] = { 0x20,0x00,0x21 ,0x00 };
//	memcpy(pbInfo,data,sizeof(data));
//	*pdwInfoLen = sizeof(data);
//	return 0;
//}
//void GetDeviceInfoCallBack()
//{
//	GetDeviceInfoRequest request;
//	request.ParseFromArray(recvBuffer, recvBufferLength);
//	DWORD pdwInfoLen = request.pdwinfolen();
//	byte pbInfo[1024];
//	DWORD returnValue = GetDeviceInfoActualCallBack(pbInfo, &pdwInfoLen, (BYTE)request.bflag());
//	GetDeviceInfoReply reply;
//	reply.set_pbinfo(bytesToHexString(pbInfo, pdwInfoLen));
//	reply.set_pdwinfolen(pdwInfoLen);
//	reply.set_returnvalue(returnValue);
//	byte data[1024] = { 0 };
//	reply.SerializeToArray(data, sizeof(data));
//	Send_Protocol(data, reply.ByteSizeLong());
//}

//被调用的实际接口 
DWORD LoadSymKey(IN BYTE bKeyType, IN WORD wKeyIndex, IN BYTE bAlg, IN BYTE bProtectKeyType, IN WORD wProtectKeyIndex, IN BYTE *pbKeyData, IN WORD wKeyDataLen, IN OUT BYTE *pbKCV, IN BYTE bKCVLen, IN BYTE bKCVMode) 
{
	std::cout << "被调用的实际接口 LoadSymKey" << std::endl;
	printf("bKeyType=%d ,wKeyIndex=%d ,bAlg=%d ,bProtectKeyType=%d ,wProtectKeyIndex=%d ,wKeyDataLen=%d \n", bKeyType, wKeyIndex, bAlg, bProtectKeyType, wProtectKeyIndex, wKeyDataLen);
	printfHexBytes("pbKeyData=", pbKeyData , wKeyDataLen);

	unsigned char kcv[] = { 0x77,0x00,0x88 ,0x00 };
	memcpy(pbKCV,kcv,sizeof(kcv));
	return 0;
}
void LoadSymKeyCallBack()
{
	LoadSymKeyRequest request;
	request.ParseFromArray(recvBuffer, recvBufferLength);
	byte pbKeyData[1024] ;
	hexStringToBytes(request.pbkeydata(), pbKeyData);
	byte pbKCV[1024];
	hexStringToBytes(request.pbkcv(), pbKCV);
	DWORD returnValue = LoadSymKey(request.bkeytype(),request.wkeyindex(),request.balg(),request.bprotectkeytype(),request.wprotectkeyindex(), pbKeyData,request.wkeydatalen(),pbKCV,request.bkcvlen(),request.bkcvmode());
	LoadSymKeyReply reply;
	reply.set_pbkcv(bytesToHexString(pbKCV,(int)request.bkcvlen() ));
	reply.set_returnvalue(returnValue);
	reply.set_messagetype(MESSAGE_TYPE_RETURN);
	byte data[1024] = { 0 };
	reply.SerializeToArray(data, sizeof(data));
	Send_Protocol(data, reply.ByteSizeLong());
}
typedef void(*pMethod)();
//所有回调接口
pMethod methods[] = { LoadSymKeyCallBack };


void InvokeMethod(int actualIndex)
{
	//request
	//实际调用接口
	//reply
	//send
	if (actualIndex < sizeof(methods) / sizeof(methods[0]))
	{
		methods[actualIndex]();
	}
	else
	{
		std::cout << "MethodIndex Error" << std::endl;
	}
}
void my_recv_processData(BYTE * pbData, WORD  wDataLen)
{
	printfHexBytes("my_recv_processData", pbData, wDataLen);
	//校验正确后处理
	if (wDataLen > 6 && Head0 == pbData[0] && Head1 == pbData[1] && wDataLen == (((((UINT)pbData[2]) << 24) + (((UINT)pbData[3]) << 16) + (((UINT)pbData[4]) << 8) + (UINT)pbData[5]) + 7) && pbData[wDataLen - 1] == crcLRC(pbData + 6, wDataLen - 7))
	{
		printfHexBytes("check OK", pbData + 6, wDataLen - 7);
		recvBufferLength = wDataLen - 7;
		memcpy(recvBuffer, pbData + 6, recvBufferLength);


		
		try {
			LoadSymKeyRequest request;
			request.ParseFromArray(recvBuffer, recvBufferLength);
			int messageType = request.messagetype();
			std::cout << "messageType=" << messageType <<" 消息类型为";
			if (messageType == MESSAGE_TYPE_RETURN)//0错误 1函数调用 2返回值
			{
				printf(" 返回值\n");
				status = true;
			}
			else if (messageType == MESSAGE_TYPE_METHOD)
			{
				int index = request.methodindex();
				printf(" 函数调用%d\n", index);
				InvokeMethod(index);				
			}
			else
			{
				printf(" 错误,即不是函数调用也不是返回值。\n");
			}
		}
		catch (...) {


		}

	}
}
int main()
{
	cout << "Start!\n";
	std::cout << "support callback methods size:" << sizeof(methods) / sizeof(methods[0]) << std::endl;
	comm.recv_processData = my_recv_processData;//接收处理函数
	comm.Connect(2); //连接
	//Send_Protocol(info, sizeof(info));//串口测试
	//comm.Disconnect();


	unsigned char info[] = { 0x20,0x00,0x21 ,0x00 };
	DWORD infoLen = sizeof(info);
	int ret = GetDeviceInfo(info, &infoLen, 1); //调用远程函数
	if (ret == 0)
	{
		std::cout << "OUT info=" << bytesToHexString(info, sizeof(info)) << std::endl;
	}


	//demo::People p;
	//p.set_id(123);
	//p.set_name( "chenhao");
	//p.set_email("11@qq.com");

	//byte array[1024] = { 0 };
	//p.SerializeToArray(array, sizeof(array));
	//printf("1  length:%02d \n", (int)p.ByteSizeLong());
	//for (int i = 0; i < p.ByteSizeLong(); i++)
	//{
	//	printf("%02X ", (int)array[i]);
	//}
	//string data;
	//p.SerializeToString(&data);
	//printf("length:%02d \n", (int)data.length());
	//for (int i = 0; i < data.length(); i++)
	//{
	//	const char* d = data.data();
	//	printf("%02X ",(int)d[i]);
	//}
	//cout << "\ndata: " << data << endl;
	//send_recv(data,&data,30);

	//demo::People2 pNew;
	//pNew.ParseFromString(data);
	//cout << "NewPeople: " << endl;
	//cout << "Name: " << pNew.name() << endl;
	//cout << "ID: " << pNew.id2() << endl;
	//cout << "Email: " << pNew.email2() << endl;

	cout << "end!\n\n";
	std::cin.get();
	// Optional:  Delete all global objects allocated by libprotobuf.
	google::protobuf::ShutdownProtobufLibrary();
	return 0;
}

B示例代码(C++)

// ConsoleApplicationProtobuf.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include "people.proto3.pb.h"
#include "D:\009protobuff\grpc-java-1.42.0\test2\pos.pb.h"
#include "./windows/commSever.h"
#include "./windows/comm_protocol.h"
#pragma comment(lib, "libprotobufd.lib")
using namespace std;

//约定:1.所有函数有函数索引,有DWORD返回值。并加上基数。
//2.byte数组 都转成十六进制字符串,收发都转。好处理些。但有些长度是指针的,直接用整型传值。
//3.结构体像单独字段一样传。
CommSever comm;
#define Head0 0xAA
#define Head1 0x55
bool status;
byte recvBuffer[2048];
int recvBufferLength;
#define RECV_TIMEOUT 10 
#define RPC_FAILED  9999
#define RPC_TIMEOUT 9998
#define MESSAGE_TYPE_ERROR  0
#define MESSAGE_TYPE_METHOD 1
#define MESSAGE_TYPE_RETURN 2

void printfHexBytes(char *memo, byte* data, int dataLength)
{
	printf("%s(%d):", memo, dataLength);
	for (int i = 0; i < dataLength; i++)
		printf("%02X ", (int)data[i]);
	printf("\n");
}
//将字符串编码成16进制数字,适用于所有字符(包括中文)
std::string encodeHexString(const std::string& str) {
	// 根据默认编码获取字节数组
	const std::string hexString = "0123456789abcdef";
	string sb;
	// 将字节数组中每个字节拆解成2位16进制整数
	for (int i = 0; i < str.length(); i++) {
		sb += hexString.at((str[i] & 0xf0) >> 4);
		sb += hexString.at((str[i] & 0x0f) >> 0);
	}
	return sb;
}
//16进制字符串转字符串
std::string hexStringToString(const std::string& hexStr)
{
	std::string ret;
	const std::string hexString = "0123456789abcdef";
	// 将每2位16进制整数组装成一个字节
	for (int i = 0; i < hexStr.length(); i += 2)
		ret += BYTE(hexString.find(hexStr.at(i)) << 4 | hexString.find(hexStr.at(i + 1)));
	return ret;
}
//字节数组转16进制字符串
std::string bytesToHexString(const BYTE* bytes, const int length)
{
	if (bytes == NULL) {
		return "";
	}
	std::string buff;
	const int len = length;
	for (int j = 0; j < len; j++) {
		int high = bytes[j] / 16, low = bytes[j] % 16;
		buff += (high < 10) ? ('0' + high) : ('a' + high - 10);
		buff += (low < 10) ? ('0' + low) : ('a' + low - 10);
	}
	return buff;
}
//16进制字符串 转 字节数组
void hexStringToBytes(const std::string& hex, BYTE* bytes)
{
	int bytelen = hex.length() / 2;
	std::string strByte;
	unsigned int n;
	for (int i = 0; i < bytelen; i++)
	{
		strByte = hex.substr(i * 2, 2);
		sscanf_s(strByte.c_str(), "%x", &n);
		bytes[i] = n;
	}
}


static BYTE crcLRC(BYTE * pbData, WORD wdataLen)
{
	BYTE bRet = 0;

	while (wdataLen--)
	{
		bRet ^= *pbData++;
	}

	return bRet;
}
int Send_Protocol(LPBYTE lpData, UINT nSize)
{
	BYTE sendData[2048];
	sendData[0] = Head0;
	sendData[1] = Head1;
	int length = nSize+7 ;
	sendData[2] = (BYTE)(nSize >> 24);//length
	sendData[3] = (BYTE)(nSize >> 16);
	sendData[4] = (BYTE)(nSize >> 8);
	sendData[5] = (BYTE)(nSize);
	memcpy(sendData + 6, lpData, nSize);
	sendData[length - 1] = (BYTE)(crcLRC(lpData, nSize)); //crch
	return comm.Send(sendData, length);
}

int send_recv(string request, int timeout)
{
	status = false;
	Send_Protocol((byte *)request.data(), request.length());
	//等待直到超时或有返回值
	for(int i=0;i<timeout*1000;i++)
	{
		if (status)
		{
			return 0;
		}
		Sleep(1);//ms
	}
	std::cout << "RPC_TIMEOUT" << std::endl;
	return RPC_TIMEOUT;
}







using pos::InitializeRequest;
using pos::InitializeReply;
using pos::FinalizeRequest;
using pos::FinalizeReply;
using pos::SetKeyGroupNameRequest;
using pos::SetKeyGroupNameReply;
using pos::LoadDukptIpekRequest;
using pos::LoadDukptIpekReply;
using pos::LoadSymKeyRequest;
using pos::LoadSymKeyReply;
using pos::GetKSNRequest;
using pos::GetKSNReply;
using pos::IncreaseKSNRequest;
using pos::IncreaseKSNReply;
using pos::LoadTr31KeyByIndexRequest;
using pos::LoadTr31KeyByIndexReply;
using pos::ExchangeKeyWithECDHRequest;
using pos::ExchangeKeyWithECDHReply;
using pos::MacByIndexRequest;
using pos::MacByIndexReply;
using pos::ManagerCertFileRequest;
using pos::ManagerCertFileReply;
using pos::getCertFileRequest;
using pos::getCertFileReply;
using pos::SetAcquirerDataRequest;
using pos::SetAcquirerDataReply;
using pos::AddAppParametersRequest;
using pos::AddAppParametersReply;
using pos::DeleteAppParametersRequest;
using pos::DeleteAppParametersReply;
using pos::DeleteAllAppParametersRequest;
using pos::DeleteAllAppParametersReply;
using pos::AddDRLRequest;
using pos::AddDRLReply;
using pos::DeleteDRLRequest;
using pos::DeleteDRLReply;
using pos::DeleteAllDRLRequest;
using pos::DeleteAllDRLReply;
using pos::AddCAPubKeyRequest;
using pos::AddCAPubKeyReply;
using pos::DeleteCAPubKeyRequest;
using pos::DeleteCAPubKeyReply;
using pos::AddPRMacqRequest;
using pos::AddPRMacqReply;
using pos::SetICSRequest;
using pos::SetICSReply;
using pos::SetInteractionPointRequest;
using pos::SetInteractionPointReply;
using pos::StartTransactionRequest;
using pos::StartTransactionReply;
using pos::ContinueTransactionRequest;
using pos::ContinueTransactionReply;
using pos::GetTlvListRequest;
using pos::GetTlvListReply;
using pos::GetEncryptedDataElementRequest;
using pos::GetEncryptedDataElementReply;
using pos::GetMsDataRequest;
using pos::GetMsDataReply;
using pos::GetVersionRequest;
using pos::GetVersionReply;
using pos::GetDeviceInfoRequest;
using pos::GetDeviceInfoReply;
using pos::UpdatePosFileRequest;
using pos::UpdatePosFileReply;

//DWORD GetDeviceInfo(OUT BYTE *pbInfo, IN OUT DWORD *pdwInfoLen, IN BYTE bFlag) {
//	// Data we are sending to the server.
//	GetDeviceInfoRequest request;
//	request.set_pdwinfolen(*pdwInfoLen);
//	request.set_bflag(bFlag);
//	// Container for the data we expect from the server.
//	GetDeviceInfoReply reply;
//
//	// Context for the client. It could be used to convey extra information to
//	// the server and/or tweak certain RPC behaviors.
//
//	// Act upon its status.
//	if (status) {
//		GetDeviceInfoReply reply;
//		reply.ParseFromArray(recvBuffer, recvBufferLength);
//		std::cout << "returnValue=" << reply.returnvalue() << std::endl;
//		hexStringToBytes(reply.pbinfo(), pbInfo);
//		std::cout << "pbInfo=" << reply.pbinfo() << std::endl;
//		*pdwInfoLen = reply.pdwinfolen();
//		std::cout << "pdwInfoLen=" << reply.pdwinfolen() << std::endl;
//		return reply.returnvalue();
//	}
//	else {
//		std::cout << "GetDeviceInfo" << " RPC_FAILED" << std::endl;
//		return RPC_FAILED;
//	}
//}
DWORD LoadSymKey(IN BYTE bKeyType, IN WORD wKeyIndex, IN BYTE bAlg, IN BYTE bProtectKeyType, IN WORD wProtectKeyIndex, IN BYTE *pbKeyData, IN WORD wKeyDataLen, IN OUT BYTE *pbKCV, IN BYTE bKCVLen, IN BYTE bKCVMode) {
	// Data we are sending to the server.
	std::cout << "invoke LoadSymKey" << std::endl;
	LoadSymKeyRequest request;
	request.set_messagetype(1);
	request.set_methodindex(0);
	request.set_bkeytype(bKeyType);
	request.set_wkeyindex(wKeyIndex);
	request.set_balg(bAlg);
	request.set_bprotectkeytype(bProtectKeyType);
	request.set_wprotectkeyindex(wProtectKeyIndex);
	request.set_pbkeydata(bytesToHexString(pbKeyData, wKeyDataLen));
	request.set_wkeydatalen(wKeyDataLen);
	request.set_pbkcv(bytesToHexString(pbKCV, bKCVLen));
	request.set_bkcvlen(bKCVLen);
	request.set_bkcvmode(bKCVMode);

	// Container for the data we expect from the server.

	// The actual RPC.
	string requestData;
	request.SerializeToString(&requestData);
	send_recv(requestData, RECV_TIMEOUT);
	// Act upon its status.
	if (status) {
		LoadSymKeyReply reply;
		reply.ParseFromArray(recvBuffer,recvBufferLength);
		std::cout << "returnValue=" << reply.returnvalue() << std::endl;
		hexStringToBytes(reply.pbkcv(), pbKCV);
		std::cout << "pbKCV=" << reply.pbkcv() << std::endl;
		return reply.returnvalue();
	}
	else {
		std::cout <<"LoadSymKey"<<" RPC_FAILED" << std::endl;
		return RPC_FAILED;
	}
}
//被调用的实际接口
DWORD GetDeviceInfo(OUT BYTE *pbInfo, IN OUT DWORD *pdwInfoLen, IN BYTE bFlag)
{
	std::cout << "被调用的实际接口 GetDeviceInfo" << std::endl;
	std::cout << "pdwInfoLen=" << *pdwInfoLen << std::endl;
	//std::cout << "bFlag=" << bFlag << std::endl; //会当成char显示
	printf("bFlag=%d\n", (int)bFlag);
	unsigned char data[] = { 0x20,0x00,0x21 ,0x00 };
	memcpy(pbInfo,data,sizeof(data));
	*pdwInfoLen = sizeof(data);
	return 0;
}
void GetDeviceInfoCallBack()
{
	GetDeviceInfoRequest request;
	request.ParseFromArray(recvBuffer, recvBufferLength);
	DWORD pdwInfoLen = request.pdwinfolen();
	byte pbInfo[1024];
	DWORD returnValue=GetDeviceInfo(pbInfo,&pdwInfoLen,request.bflag());
	GetDeviceInfoReply reply;
	reply.set_pbinfo(bytesToHexString(pbInfo, pdwInfoLen));
	reply.set_pdwinfolen(pdwInfoLen);
	reply.set_returnvalue(returnValue);
	reply.set_messagetype(MESSAGE_TYPE_RETURN);
	byte data[1024] = {0};
	reply.SerializeToArray(data,sizeof(data));
	Send_Protocol(data, reply.ByteSizeLong());
}
typedef void(*pMethod)();
//所有回调接口
pMethod methods[] = { GetDeviceInfoCallBack,GetDeviceInfoCallBack,GetDeviceInfoCallBack };


void InvokeMethod(int actualIndex)
{
	//request
	//实际调用接口
	//reply
	//send
	if (actualIndex < sizeof(methods) / sizeof(methods[0]))
	{
		methods[actualIndex]();
	}
	else
	{
		std::cout << "MethodIndex Error" << std::endl;
	}
}
void my_recv_processData(BYTE * pbData, WORD  wDataLen)
{
	printfHexBytes("my_recv_processData", pbData, wDataLen);
	//校验正确后处理
	if (wDataLen > 6 && Head0 == pbData[0] && Head1 == pbData[1] && wDataLen == (((((UINT)pbData[2]) << 24) + (((UINT)pbData[3]) << 16) + (((UINT)pbData[4]) << 8) + (UINT)pbData[5]) + 7) && pbData[wDataLen - 1] == crcLRC(pbData + 6, wDataLen - 7))
	{
		printfHexBytes("check OK", pbData + 6, wDataLen - 7);
		recvBufferLength = wDataLen - 7;
		memcpy(recvBuffer, pbData + 6, recvBufferLength);



		try {
			LoadSymKeyRequest request;
			request.ParseFromArray(recvBuffer, recvBufferLength);
			int messageType = request.messagetype();
			std::cout << "messageType=" << messageType << " 消息类型为";
			if (messageType == MESSAGE_TYPE_RETURN)//0错误 1函数调用 2返回值
			{
				printf(" 返回值\n");
				status = true;
			}
			else if (messageType == MESSAGE_TYPE_METHOD)
			{
				int index = request.methodindex();
				printf(" 函数调用%d\n", index);
				InvokeMethod(index);
			}
			else
			{
				printf(" 错误,即不是函数调用也不是返回值。\n");
			}
		}
		catch (...) {


		}

	}
}
int main()
{
	cout << "Start!\n";
	std::cout << "support callback methods size:" << sizeof(methods) / sizeof(methods[0]) << std::endl;
	comm.recv_processData = my_recv_processData;//接收处理函数
	comm.Connect(1); //连接
	//Send_Protocol(info, sizeof(info));
	//comm.Disconnect();

	unsigned char keyData[] = { 0x10,0x00,0x11 ,0x00 };
	unsigned char kcv[] = { 0x20,0x00,0xF1 ,0xFF };
	int ret=LoadSymKey(1, 2, 3, 4, 5, keyData, sizeof(keyData), kcv, sizeof(kcv), 10);
	if(ret==0)
	{
		std::cout << "OUT pbKCV=" << bytesToHexString(kcv, sizeof(kcv)) << std::endl;
	}



	//demo::People p;
	//p.set_id(123);
	//p.set_name( "chenhao");
	//p.set_email("11@qq.com");

	//byte array[1024] = { 0 };
	//p.SerializeToArray(array, sizeof(array));
	//printf("1  length:%02d \n", (int)p.ByteSizeLong());
	//for (int i = 0; i < p.ByteSizeLong(); i++)
	//{
	//	printf("%02X ", (int)array[i]);
	//}
	//string data;
	//p.SerializeToString(&data);
	//printf("length:%02d \n", (int)data.length());
	//for (int i = 0; i < data.length(); i++)
	//{
	//	const char* d = data.data();
	//	printf("%02X ",(int)d[i]);
	//}
	//cout << "\ndata: " << data << endl;
	send_recv(data,&data,30);

	//demo::People2 pNew;
	//pNew.ParseFromString(data);
	//cout << "NewPeople: " << endl;
	//cout << "Name: " << pNew.name() << endl;
	//cout << "ID: " << pNew.id2() << endl;  //结果123
	//cout << "Email: " << pNew.email2() << endl;

    cout << "end!\n";
	std::cin.get();
	// Optional:  Delete all global objects allocated by libprotobuf.
	google::protobuf::ShutdownProtobufLibrary();
	return 0;
}

代码自动生成:从C++头文件生成proto、C++ client、Java Server

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//约定:
//1.所有消息增加消息类型  int32 messageType = 1;,值定义:0错误(默认值,不使用) 1函数调用 2返回值。
//2.所有函数增加函数索引  int32 methodIndex = 2;。
//3.所有返回值字段名用returnValue
//4.byte数组 都转成十六进制字符串,收发都转。好处理些。但所有长度是指针的,直接用整型传值。
//5.结构体像单独字段一样传,顺序不变。
public class AutoGenerategRPC {
    public static final String FILENAME="pos.h"; //原始接口头文件

    public static final String PACKAGE="pos"; //要生成的proto中package
    public static final String SERVICE="SdkInterface"; //要生成的proto中service
    public static final String RETURNVALUE="returnValue"; //要生成的proto中函数返回值,void即为空
    public static final String METHOD_INDEX="methodIndex"; //要生成的proto中函数索引
    public static final String MESSAGE_Type="messageType"; //消息类型 0错误 1函数 2返回值
    public static final int MAX_BUFFER=2048; //最大缓冲
    public static void main(String[] args) {
        //test();
        generateFileProto(); //OK for pb ,add int32 methodName as index, end With Len  pointer  remove pointer。
        generateFileCPPClient();
        generateFileJavaServer();
        generateFileCPPClientProtoBuf();
        generateFileJavaServerProtoBuf();
    }
    private static void generateFileCPPClientProtoBuf() {
        String using="";
        String methods="";
        ArrayList<Method> mList=getMethods(FILENAME);
        int methodIndex=0;
        for(Method m:mList) {
            using += "using " + PACKAGE + "::" + m.methodName + "Request;\n" +
                    "using " + PACKAGE + "::" + m.methodName + "Reply;\n";

            String tempRequest="";
            tempRequest+=
                    "      request.set_messagetype(1);\n" +
                    "      request.set_methodindex("+(methodIndex++)+");\n";
            for (int i=0;i<m.inList.size();i++) {
                if(m.inList.get(i).type.contains("BYTE*"))
                {
                    String length="5";
                    if(i+1<m.inList.size() && m.inList.get(i+1).name.endsWith("Len"))
                    {
                        length= m.inList.get(i+1).name;
                    }
                    tempRequest += "      request.set_" + m.inList.get(i).name.toLowerCase() + "(bytesToHexString(" + m.inList.get(i).name + ","+length+"));\n";
                }
                else if(m.inList.get(i).name.endsWith("Len") && m.inList.get(i).string.contains("*"))
                {
                    tempRequest += "      request.set_" + m.inList.get(i).name.toLowerCase() + "(*" + m.inList.get(i).name + ");\n";
                }
                else
                {
                    tempRequest += "      request.set_" + m.inList.get(i).name.toLowerCase() + "(" + m.inList.get(i).name + ");\n";
                }
            }
            String tempReply="";
            for (int i=0;i<m.outList.size();i++) {
                if(m.outList.get(i).type.contains("BYTE*"))
                {
                    tempReply+="          hexStringToBytes(reply."+m.outList.get(i).name.toLowerCase()+"(),"+m.outList.get(i).name+");\n";
                }
                else if(m.outList.get(i).name.endsWith("Len") && m.outList.get(i).string.contains("*")) // OUT
                {
                    tempReply+="          *"+m.outList.get(i).name+"=reply."+m.outList.get(i).name.toLowerCase()+"();\n";
                }
                tempReply+="          std::cout << \""+m.outList.get(i).name+"=\" << reply."+m.outList.get(i).name.toLowerCase()+"() << std::endl;\n";
            }

            methods += "  "+m.methodLine.replace(";", "") + "{\n" +
                    "      // Data we are sending to the server.\n" +
                    "      "+m.methodName+"Request request;\n" +

                    tempRequest+

                    "      string requestData;\n" +
                    "      request.SerializeToString(&requestData);\n"+
                    "      send_recv(requestData, RECV_TIMEOUT);\n" +
                    "      // Act upon its status.\n" +
                    "      if (status) {\n" +
                    "          "+m.methodName+"Reply reply;\n" +
                    "          reply.ParseFromArray(recvBuffer,recvBufferLength);\n"+
                    "          std::cout << \"returnValue=\" << reply."+RETURNVALUE.toLowerCase()+"() << std::endl;\n" +

                    tempReply+

                    "          return reply."+RETURNVALUE.toLowerCase()+"();\n" +
                    "      }\n" +
                    "      else {\n" +
                    "          std::cout <<\""+m.methodName+"\"<<\" RPC_FAILED\" << std::endl;\n" +
                    "          return RPC_FAILED;\n" +
                    "      }\n" +
                    "  }\n\n";
        }

        String contents=
                "namespace "+SERVICE+" {\n" +
                using+"\n\n"+
                methods+"\n"+
                "}\n";                ;
        writeToFile(SERVICE+"ProtoBuf.cc",contents,false); //写入文件
    }


    private static void generateFileJavaServerProtoBuf()
    {
        String methods="";
        ArrayList<Method> mList=getMethods(FILENAME);
        for(Method m:mList) {
            String tempRequest="";
            String temp="";
            for (int i=0;i<m.inList.size();i++) {
                if(m.inList.get(i).type.contains("BYTE*"))
                {
                    temp+="hexStringToBytes(req.get"+upperFirstLatter(m.inList.get(i).name)+"()),";
                }
                else
                {
                    temp += "req.get" + upperFirstLatter(m.inList.get(i).name) + "(),";
                }
            }
            for (int i=0;i<m.outList.size();i++) {
                if(m.outList.get(i).isOut && !m.outList.get(i).isIn)
                {
                    if(m.outList.get(i).type.contains("BYTE*")) {
                        tempRequest += "        " + typeTranslate(ParaType.JAVA, m.outList.get(i).type) + " byte[] " + m.outList.get(i).name + "=new byte["+MAX_BUFFER+"];\n";
                    }
                    temp += m.outList.get(i).name+",";
                }
            }
            if(temp.endsWith(",")) //存在参数
            {
                temp=temp.substring(0,temp.length()-1);
                tempRequest+="        "+m.methodName+"Request req="+m.methodName+"Request.parseFrom(recvByteArray);\n";
            }

            tempRequest+="        "+typeTranslate(ParaType.JAVA,m.returnType)+" returnValue = "+m.methodName+"("+temp+"); //实际接口\n";

            String tempReply="";
            tempReply+=".setReturnValue(returnValue)";
            tempReply+=".setMessageType(MESSAGE_TYPE_RETURN)";
            for (int i=0;i<m.outList.size();i++){
                if(m.outList.get(i).type.contains("BYTE*"))
                {
                    String length="??";
                    if(i+1<m.outList.size() && m.outList.get(i+1).name.endsWith("Len"))
                    {
                        length= m.outList.get(i+1).name;
                    }
                    tempReply+=".set"+upperFirstLatter(m.outList.get(i).name)+"(bytesToHexString("+m.outList.get(i).name+","+length+"))";
                }
                else if(m.outList.get(i).name.endsWith("Len") && m.outList.get(i).string.contains("*")) // OUT
                {
                    tempReply+=".set"+upperFirstLatter(m.outList.get(i).name)+"("+m.outList.get(i).name+")";
                }
            }

            methods +=
            "    public void " + m.methodName + "Server() {\n" +
            tempRequest+

            "        "+ m.methodName +"Reply reply = "+ m.methodName +"Reply.newBuilder()"+tempReply+".build();\n"+
            "        Send_Protocol(reply.toByteArray());\n" +
            "    }\n" ;
        }
        String contents=
                "public class "+SERVICE+"ProtoBuf {\n" +
                        methods+
                        "}\n";

        writeToFile(SERVICE+"ProtoBuf.java",contents,false); //写入文件
    }
    private static void generateFileJavaServer() {
        String methods="";
        ArrayList<Method> mList=getMethods(FILENAME);
        for(Method m:mList) {
            String tempRequest="";
            for (Para p : m.inList) {
                tempRequest+="                System.out.println(req.get"+p.name+"());\n"; //对接java接口
            }
            String tempReply="";
            for (Para p : m.outList) {
                tempReply+=".set"+p.name+"(\"HELLO\")"; //对接java接口
            }

            methods +=
                    "            @Override\n" +
                            "            public void " + m.methodName + "(" + m.methodName + "Request req, StreamObserver<" + m.methodName + "Reply> responseObserver) {\n" +
                            tempRequest+
                            "                "+ m.methodName +"Reply reply = "+ m.methodName +"Reply.newBuilder()"+tempReply+".build();\n"+
                            "                responseObserver.onNext(reply);\n" +
                            "                responseObserver.onCompleted();\n" +
                            "            }\n" ;
        }



        String contents=
                "        static class "+SERVICE+"Impl extends "+SERVICE+"Grpc."+SERVICE+"ImplBase {\n" +
                        methods+
                        "        }\n";

        writeToFile(PACKAGE+".java",contents,false); //写入文件
    }

    private static void generateFileCPPClient() {
        String using="";
        String methods="";
        ArrayList<Method> mList=getMethods(FILENAME);
        for(Method m:mList) {
            using += "using " + PACKAGE + "::" + m.methodName + "Request;\n" +
                    "using " + PACKAGE + "::" + m.methodName + "Reply;\n";


            String tempRequest="";

            for (int i=0;i<m.inList.size();i++) {
                if(m.inList.get(i).type.contains("BYTE*"))
                {
                    String length="5";
                    if(i+1<m.inList.size() && m.inList.get(i+1).name.endsWith("Len"))
                    {
                        length= m.inList.get(i+1).name;
                    }
                    tempRequest += "      request.set_" + m.inList.get(i).name.toLowerCase() + "(bytesToHexString(" + m.inList.get(i).name + ","+length+"));\n";
                }
                else if(m.inList.get(i).name.endsWith("Len") && m.inList.get(i).string.contains("*"))
                {
                    tempRequest += "      request.set_" + m.inList.get(i).name.toLowerCase() + "(*" + m.inList.get(i).name + ");\n";
                }
                else
                {
                    tempRequest += "      request.set_" + m.inList.get(i).name.toLowerCase() + "(" + m.inList.get(i).name + ");\n";
                }
            }
            String tempReply="";
            for (int i=0;i<m.outList.size();i++) {
                if(m.outList.get(i).type.contains("BYTE*"))
                {
                    tempReply+="          hexStringToBytes(reply."+m.outList.get(i).name.toLowerCase()+"(),"+m.outList.get(i).name+");\n";
                }
                else if(m.outList.get(i).name.endsWith("Len") && m.outList.get(i).string.contains("*")) // OUT
                {
                    tempReply+="          *"+m.outList.get(i).name+"="+m.outList.get(i).name.toLowerCase()+"();\n";
                }
                tempReply+="          std::cout << \""+m.outList.get(i).name+"=\" << reply."+m.outList.get(i).name.toLowerCase()+"() << std::endl;\n";
            }

            methods += "  "+m.methodLine.replace(";", "") + "{\n" +
                    "      // Data we are sending to the server.\n" +
                    "      "+m.methodName+"Request request;\n" +

                    tempRequest+

                    "      // Container for the data we expect from the server.\n" +
                    "      "+m.methodName+"Reply reply;\n" + "\n" +
                    "      // Context for the client. It could be used to convey extra information to\n" +
                    "      // the server and/or tweak certain RPC behaviors.\n" +
                    "      ClientContext context;\n" + "\n" +
                    "      // The actual RPC.\n" +
                    "      Status status = stub_->"+m.methodName+"(&context, request, &reply);\n" + "\n" +
                    "      // Act upon its status.\n" +
                    "      if (status.ok()) {\n" +
                    "          std::cout << \"returnValue=\" << reply."+RETURNVALUE.toLowerCase()+"() << std::endl;\n" +

                    tempReply+

                    "          return reply."+RETURNVALUE.toLowerCase()+"();\n" +
                    "      }\n" +
                    "      else {\n" +
                    "          std::cout << status.error_code() << \": \" << status.error_message() << std::endl;\n" +
                    "          return RPC_FAILED;\n" +
                    "      }\n" +
                    "  }\n\n";
        }

        String contents="using grpc::Channel;\n" +
                "using grpc::ClientContext;\n" +
                "using grpc::Status;\n" +
                "using "+PACKAGE+"::"+SERVICE+";\n"+
                using+"\n\n"+
                "class "+SERVICE+"Client {\n" +
                " public:\n" +
                "  "+SERVICE+"Client(std::shared_ptr<Channel> channel) : stub_("+SERVICE+"::NewStub(channel)) {}\n"+
                methods+"\n"+
                " private:\n" +
                "  std::unique_ptr<Greeter::Stub> stub_;\n" +
                "};\n";                ;
        writeToFile(PACKAGE+"Client.cc",contents,false); //写入文件
    }

    public static void generateFileProto()
    {
        String method="";
        String para="";

        ArrayList<Method> mList=getMethods(FILENAME);
        for(Method m:mList)
        {
            method+="  rpc "+m.methodName+" ("+m.methodName+"Request) returns ("+m.methodName+"Reply) {}\n";

            String tempRequest="";
            int index=1;

            tempRequest+="  "+typeTranslate(ParaType.PROTO,"int")+" "+MESSAGE_Type+" = "+index+";\n"; index++;//messageType for protobuf
            tempRequest+="  "+typeTranslate(ParaType.PROTO,"int")+" "+METHOD_INDEX+" = "+index+";\n"; index++;//method index for protobuf
            for (Para p : m.inList) {
                tempRequest+="  "+typeTranslate(ParaType.PROTO,p.type) + " " + p.name+" = "+index+";\n";
                index++;
            }
            String tempReply="";
            index=1; //返回值占了1
            tempReply+="  "+typeTranslate(ParaType.PROTO,"int")+" "+MESSAGE_Type+" = "+index+";\n"; index++;//messageType for protobuf
            tempReply+="  "+typeTranslate(ParaType.PROTO,m.returnType)+" "+RETURNVALUE+" = "+index+";\n"; index++;//return value for protobuf
            for (Para p : m.outList) {
                tempReply+="  "+typeTranslate(ParaType.PROTO,p.type) + " " + p.name+" = "+index+";\n";
                index++;
            }
            para+="message "+m.methodName+"Request {\n" +
                    tempRequest +
                    "}\n";
            para+="message "+m.methodName+"Reply {\n" +
                    tempReply +
                    "}\n";
        }


        String contents="/* DO NOT EDIT THIS FILE - it is machine generated */\n"+
                "syntax = \"proto3\";\n" +
                " \n" +
                "option java_multiple_files = true;\n" +
                "option java_package = \"io.grpc.auto."+PACKAGE.toLowerCase()+"\";\n" +
                "option java_outer_classname = \""+SERVICE+"Proto\";\n" +
                "option objc_class_prefix = \""+PACKAGE.toUpperCase()+"\";\n" +
                "package "+PACKAGE+";\n" +
                " \n" +
                "service  "+SERVICE+"{"
                +method +
                "}\n"+ para;
        writeToFile(PACKAGE+".proto",contents,false); //写入文件
    }


    enum ParaType{PROTO, CPP, JAVA,  }
    public static String typeTranslate(ParaType t, String type)
    {
        if(t==ParaType.PROTO)
        {
            return Constant.TYPE_PROTO.get(type);
        }
        else if(t==ParaType.CPP)
        {

        }
        else  if(t==ParaType.JAVA)
        {
            return Constant.TYPE_JAVA.get(type);
        }
        else
        {

        }
        return "";
    }

    static class Constant {
        public static final Map<String, String> TYPE_PROTO = new HashMap<>();
        static {
            TYPE_PROTO.put("byte", "int32"); //c++,proto
            TYPE_PROTO.put("BYTE", "int32");
            TYPE_PROTO.put("WORD", "int32");
            TYPE_PROTO.put("short", "int32");
            TYPE_PROTO.put("int", "int32");
            TYPE_PROTO.put("DWORD", "int32");
            TYPE_PROTO.put("BYTE*", "bytes");
            TYPE_PROTO.put("BYTE[]", "bytes");
            TYPE_PROTO.put("byte[]", "bytes");
            TYPE_PROTO.put("char*", "bytes");
            TYPE_PROTO.put("WORD*", "bytes");
            TYPE_PROTO.put("DWORD*", "bytes");
        }

        public static final Map<String, String> TYPE_JAVA = new HashMap<>();
        static {
            TYPE_JAVA.put("byte", "int"); //c++,JAVA
            TYPE_JAVA.put("BYTE", "int");
            TYPE_JAVA.put("WORD", "int");
            TYPE_JAVA.put("short", "int");
            TYPE_JAVA.put("int", "int");
            TYPE_JAVA.put("DWORD", "int");
            TYPE_JAVA.put("BYTE*", "byte[]");
            TYPE_JAVA.put("BYTE[]", "byte[]");
            TYPE_JAVA.put("byte[]", "byte[]");
            TYPE_JAVA.put("char*", "byte[]");
            TYPE_JAVA.put("WORD*", "byte[]");
            TYPE_JAVA.put("DWORD*", "byte[]");
        }
    }
    public static void test()
    {
        ArrayList<Method> mList=getMethods("pos.h");
        for(Method m:mList)
        {
            System.out.println(m.returnType +" "+m.methodName);
            for (Para p : m.inList) {
                System.out.println(p.type + " " + p.name);
            }
            for (Para p : m.outList) {
                System.out.println(p.type + " " + p.name);
            }
        }
    }

    static class Para{
        String string;
        boolean isIn;
        boolean isOut;
        String type; //参数类型
        String name; //参数名
    }
    static class Method{
        String methodLine;
        String methodName; //函数名
        String returnType; //返回类型
        ArrayList<Para> inList =new ArrayList<>();
        ArrayList<Para> outList =new ArrayList<>();
    }
    public static ArrayList<Method> getMethods(String fileName)
    {
        ArrayList<Method> mList=new ArrayList<>();
        ArrayList<String> arrayList =readFile(fileName);
        for(String line:arrayList)
        {
            mList.add(getMethod(line));
        }
        return mList;
    }

    public static Method getMethod(String line)
    {
        Method method=new Method();
        method.methodLine=line;
        method.methodName= getRegEx(line,"(?<=\\s).*?(?=\\()").trim();
        method.returnType=getRegEx(line,".*?(?=\\s)").trim(); //返回值 函数名前
        String paraStr=getRegEx(line,"(?<=\\().*?(?=\\))").trim(); //()中内容
        String[] paras=paraStr.split(","); //按,分割成单个参数
        if(paras.length==0) //无参数
        {

        }
        else { //有参数
            for (String para : paras) {
                //System.out.println(para.trim());
                if (para.trim().equals("void")) //无参数
                {

                } else {    //有参数
                    String[] part = para.split(" "); //按空格分割 单个参数 IN OUT BYTE bKeyType
                    if(part.length>2) {
                        if (para.contains("*") ) //指针类型
                        {
                            part[part.length - 1] = part[part.length - 1].replace("*", ""); //参数名
                            if(part[part.length - 1].endsWith("Len"))
                            {
                                part[part.length - 2] = part[part.length - 2].replace("*", ""); //类型
                            }
                            else
                            {
                                part[part.length - 2] = part[part.length - 2].replace("*", "")+"*"; //类型 指针合并到类型中
                            }

                        }
                        if(para.contains("[") ) //也是指针类型,可能有[]、[2]
                        {
                            part[part.length - 1] = part[part.length - 1].replaceAll("\\[[0-9]*?\\]", ""); //参数名
                            if(part[part.length - 1].endsWith("Len"))
                            {
                                part[part.length - 2] = part[part.length - 2].replaceAll("\\[[0-9]*?\\]", ""); //类型
                            }
                            else
                            {
                                part[part.length - 2] = part[part.length - 2].replaceAll("\\[[0-9]*?\\]", "")+"*"; //类型 指针合并到类型中
                            }


                        }
                        Para p=new Para();
                        p.string=para;
                        p.type=part[part.length - 2]; //类型
                        p.name=part[part.length - 1]; //参数名
                        if(p.isIn=para.contains("IN"))
                        {
                            method.inList.add(p);
                        }
                        if(p.isOut=para.contains("OUT"))
                        {
                            method.outList.add(p);
                        }
                    }
                }
            }
        }
        return method;
    }
    /**
     * 功能:
     * @param str 要匹配的字符串
     * @param reg 正则表达式
     * @return 返回“”或1条匹配结果
     */
    public static String getRegEx(String str,String reg)  //返回0或1条匹配结果
    {
        String result="";
        // 创建 Matcher 对象
        Matcher m = Pattern.compile(reg, Pattern.COMMENTS).matcher(str);
        if( m.find() )
        {
            result = m.group();
        }
        return result;
    }

    public static void writeToFile(String pathName,String contents,boolean append)
    {
        try{
            File file =new File(pathName);
            if(!file.exists()){ //if file doesnt exists, then create it
                file.createNewFile();
            }
            FileWriter fileWritter = new FileWriter(file.getName(),append);//true = append file
            fileWritter.write(contents);
            fileWritter.close();
            System.out.println("write Done");
        }catch(IOException e){
            e.printStackTrace();
        }
    }
    public static String manualReplaceSpecial(String line)
    {
        line=line.replace("IN TRANSACTION_OPTIONS *pstTransactionOptions","IN BYTE bPINEncKeyType,IN BYTE pbPINEncKeyIndex[2],IN BYTE bWorkingKeyAlg,IN BYTE bPINBlockFormat,IN BYTE bMagTransServiceCodeProcess,IN BYTE pbPINPolicy[2],IN BYTE pbPINLen[2],IN BYTE bMAGTransOnlinePIN");
        return line;
    }
    public static ArrayList<String> readFile(String name) {
        // 使用ArrayList来存储每行读取到的字符串
        ArrayList<String> arrayList = new ArrayList<>();
        try {
            FileReader fr = new FileReader(name);
            BufferedReader bf = new BufferedReader(fr);
            String line;
            // 按行读取字符串
            while ((line = bf.readLine()) != null) {
                line=line.trim(); //去掉首尾空格
                while(line.contains("  ")) { //去掉所有多余空格
                    line = line.replace("  ", " "); //多个空格全合并成一个
                }
                if(!line.equals("") && !line.startsWith("//")) { //去掉空行和注释行
                    line=manualReplaceSpecial(line);//手工替换特殊内容 结构体等
                    arrayList.add(line);
                    //System.out.println(line);
                }
            }
            bf.close();
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return arrayList;
    }
    /**
     * 首字母大写
     * @param letter
     * @return
     */
    public static String upperFirstLatter(String letter){
        return letter.substring(0, 1).toUpperCase()+letter.substring(1);
    }
}

版权声明:本文为CSDN博主「小黄人软件」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chenhao0568/article/details/121427299

生成海报
点赞 0

小黄人软件

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

Camera HIDL接口实现camera preview功能

项目背景 为了在工厂测试中快速启动芯片外设测试项目,而不启动Android系统,使用fastmmi(FFBM: Fast Factory Boot Mode)测试框架。本人负责测试芯片中

ESP8266 无限重启踩坑

最近做了一个电子墨水屏万年历,在移植屏幕代码时遇到了esp8266无限软复位的问题,如果你的串口打印是以下图片所示,那么恭喜你问题解决了。 造成软复位的原因是因为,程序里有死循环&#xf

Keil MDK5 STM32F103C8T6开发环境配置

Windows下使用Keil MDK5进行stm32f103c8t6的开发和编译, 配合ST-LINK工具进行烧录, 使用原生(非HAL)的方式. 所需硬件 stm32f103系列开发板 stm32f103c8t6核心板 参数 ARM 32-b