Bug Example
Protobuf-lua has a bug:
An error occurs when you import other proto message types
If there are two Proto:reward and mail.
Where Mail's proto imported the reward message type
Reward.proto is as follows:
Package reward;
Message reward
{
optional UInt32 money = 1;
}
Mail.proto is as follows:
Import "Reward.proto";
Package mail;
Message Mail
{
optional UInt32 id = 1;
Optional reward. Reward reward = 2;
}
The code that runs is as follows:
--optional Run code--
send--local
SendMail = MAIL_PB. Mail ()
sendmail.id = local
reward = Sendmail.reward
Reward.money =
printf (sendMail)
-- Analog Receive--local
Recvmail = MAIL_PB. Mail ()
recvmail:parsefromstring (sendmail:serializetostring ())
printf (recvmail)
Very simple code, but unfortunately the error.
[string "Protobuf.lua"]:363:attempt to index Upvalue ' Message_type ' (a nil value)
Reward this message type will not be an error if defined in mail, but this can occur once you have imported it in other proto ways.
Similarly, changing the optional type of a field to the repeated type will also cause an error. code and examples are as follows:
Mail.proto:
Import "Reward.proto";
Package mail;
Message Mail
{
optional UInt32 id = 1;
Repeated reward. Reward reward = 2;
}
To run the code:
--repeated Run code--
send--local
SendMail = MAIL_PB. Mail ()
sendmail.id = A for i=1,10 does local
reward = SendMail.reward:add ()
Reward.money = 30+i
End
printf (sendMail)--
analog Receive--local
Recvmail = MAIL_PB. Mail ()
recvmail:parsefromstring (sendmail:serializetostring ())
printf (recvmail)
Error:
[string ' Containers.lua ']:27:attempt to call field ' _concrete_class ' (a nil value)
Check a lap, found that in fact, Proto-lua did not consider the introduction of other proto; his default message type is local.
See the LUA files that he automatically generates.
Pass
Protoc.exe--plugin=protoc-gen-lua= "Xxx\protoc-gen-lua.bat"--lua_out=xx\youroutdir-i=xxx\inputdir XX\ Inputdir\reward.proto Xx\inputdir\mail.proto
(How to build under Windows platform)
Generate Mail_pb.lua and Reward_pb.lua files.
One of the Mail_pb.lua screenshots is as follows:
The inspection found thatthe Reward_pb_reward message type did not exist at all. no wonder they report nil mistakes. Solution
There are two types of solutions to think about:
1. Hang the reward type in the REWARD_PB to REWARD_PB, not as a local variable
2. Change the Reward_pb_reward into REWARD_PB. Reward, and modify the corresponding code
GitHub already has the first implementation of the method, linked as follows:
Https://github.com/sean-lin/protoc-gen-lua/pull/7
While this approach can solve the problem, individuals feel too violent. The original author may not want mail, reward, etc. this type of uppercase message types exposed outside, in addition, it will increase the beginner's confusion: I am in the end with mail or mail it.
In order to retain the author's original intention, I used a second method to achieve.
Three files need to be changed:
1.protoc-gen-lua ( change the automatic generation of rules , the purpose of reward_pb_reward change to REWARD_PB. Reward)
2.protobuf.lua ( Modify optional send and receive )
3.containers.lua ( Modify the Add function for repeated )
The following explains the main changes of each file, the details of the implementation of the specific I put on the GitHub, links are as follows:
Https://github.com/sean-lin/protoc-gen-lua/pull/22
GitHub several great gods for a long time did not maintain, those several pullrequest have not handled. So maybe you'll have to change your own hands. 1.protoc-gen-lua Modification
Determine if the FIELD_DESC comes from another package, is unchanged;
The code is as follows:
Type_name = Env.get_ref_name (field_desc.type_name)
if not type_name.split ('. ') [0] in [filename+ "_PB" for filename in includes]:
type_name = Type_name.upper (). replace ('. ', ' _ ')
2.protobuf.lua Modification
Protobuf-lua two types of objects in the implementation to differentiate between messages and domains, respectively, message and descriptor.
Like mail and reward belong to descriptor, but mail and reward belong to the message.
If the reward type is replaced with a reward type, it is conceivable that his object type has changed from descriptor to message.
The source of the study can be found that if the domain of a message uses other message types, such as mail used reward. Then he's going to call Reward._concrete_class to create the message object, which is similar in form: Reward._concrete_class ()
What is that reward._concrete_class?
The check found out he was reward!.
Reward is a message type that can be invoked directly. Because he wrote the __call function in the meta table, it can be called directly. That's why we can use MAIL_PB. Mail () causes the mail message object to be created.
The other message type is not _concrete_class this field.
So the modification scheme is very clear, as long as the Reward._concrete_class () replaced by reward () can be.
Find the error (there are two places, respectively in the sending and receiving code): Message_type._concrete_class (), replaced by the following:
(Message_type._concrete_class and Message_type._concrete_class ()) or Message_type ()
3.containers.lua Modification
Optional need to modify the message, but for repeated, only need to modify one, that is, in the Containers.lua add function. This is because the repeated domain does not directly participate in the process of receiving the message, as long as it is guaranteed that the object created is correct.
The modification is similar to the Message_descriptor._concrete_class (), replaced by:
(Message_descriptor._concrete_class and Message_descriptor._concrete_class ()) or Message_descriptor ()
After these three points of change, ran again the two examples, perfect through. The results will not be posted. If there is a mistake, please correct me.