Resolve Protobuf-lua Import Other proto bugs

Source: Internet
Author: User
Tags lua
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.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.