文章目录[隐藏]
需求:
现在有函数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
暂无评论