cocos2dx lua 集成 google protobuf

选择支持google protobuf的lua库

  • 选择了几个相对质量不错的库
  1. lua-protobuf,A Lua module to work with Google protobuf
  2. pbc,A protocol buffers library for C
  3. LuaPbIntf,Binding Protobuf 3 to Lua 5.3
  4. libprotolua,A Lua module to work with Google protobuf
  • 经过对比,pbc相对名气比较大,且已有蛮多人使用于cocos2dx项目,比较成熟;问题是目测不支持proto3,在lua5.1环境下不支持int64(cocos2dx使用的是luajit2.x,对应lua5.1的版本,可以排除LuaPbIntf);整个对比不细说,总的来说pbc>lua-protobuf>libprotolua,所以这边选择pbc集成

pbc集成

  • 添加c源码:在“frameworks\cocos2d-x\external\pbc”目录下添加pbc源码(pbc/src),并在本目录下添加CMakeLists.txt(Android studio默认是使用cmake编译了)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    cmake_minimum_required(VERSION 3.6)

    set(lib_name pbc)
    set(target_name ext_${lib_name})

    project(${lib_name})

    set(${target_name}_src
    alloc.c
    array.c
    bootstrap.c
    context.c
    decode.c
    map.c
    pattern.c
    proto.c
    register.c
    rmessage.c
    stringpool.c
    varint.c
    wmessage.c
    )

    add_library(${target_name} STATIC
    ${${target_name}_src}
    )

    target_include_directories(${target_name} PUBLIC ..)

    set_target_properties(${target_name}
    PROPERTIES
    ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
    FOLDER "External"
    )
  • 修改c源码对应的cmake脚本:在“frameworks\cocos2d-x\external”目录的CMakeList.txt添加以下内容

    1
    2
    # 在add_subdirectory(md5)后添加
    add_subdirectory(pbc)
  • 添加lua绑定源码:在“frameworks\cocos2d-x\cocos\scripting\lua-bindings\manual\pbc”目录添加lua绑定代码(pbc-lua.c、pbc-lua.h、lua_cocos2dx_pbc_manual.cpp、lua_cocos2dx_pbc_manual.h)

  1. pbc-lua.c 为 “pbc/binding/lua/pbc-lua.c”

  2. pbc-lua.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// pbc-lua.h
#pragma once

#ifdef __cplusplus
extern "C" {
#endif
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus
extern "C" {
#endif
int luaopen_protobuf_c(lua_State *L);
#ifdef __cplusplus
}
#endif
  1. lua_cocos2dx_pbc_manual.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// lua_cocos2dx_pbc_manual.cpp
#include "scripting/lua-bindings/manual/pbc/lua_cocos2dx_pbc_manual.h"

#include "platform/CCPlatformConfig.h"
#include "base/ccConfig.h"
#include "scripting/lua-bindings/manual/tolua_fix.h"
#include "scripting/lua-bindings/manual/LuaBasicConversions.h"
#include "scripting/lua-bindings/manual/CCLuaEngine.h"

#include "scripting/lua-bindings/manual/pbc/pbc-lua.h"

#include "cocos/platform/CCFileUtils.h"

int read_protobuf_file(lua_State *L){
const char *buff = luaL_checkstring(L, -1);
Data data = cocos2d::FileUtils::getInstance()->getDataFromFile(buff);
lua_pushlstring(L, (const char*)data.getBytes(), data.getSize());
return 1;
}

TOLUA_API int register_pbc_module(lua_State* L)
{
lua_getglobal(L, "_G");
if (lua_istable(L, -1))//stack:...,_G,
{
lua_register(L, "read_protobuf_file_c", read_protobuf_file);
luaopen_protobuf_c(L);
}
lua_pop(L, 1);
return 1;
}
  1. lua_cocos2dx_pbc_manual.h
1
2
3
4
5
6
7
8
9
10
11
12
# lua_cocos2dx_pbc_manual.h
#pragma once

#ifdef __cplusplus
extern "C" {
#endif
#include "tolua++.h"
#ifdef __cplusplus
}
#endif

TOLUA_API int register_pbc_module(lua_State* L);
  • 修改lua绑定源码的cmake脚本:修改“frameworks\cocos2d-x\cocos\scripting\lua-bindings”下的CMakeList.txt
1
2
# 在lua_bindings_manual_headers最后面添加manual/pbc/lua_cocos2dx_pbc_manual.h、manual/pbc/pbc-lua.h
# 在lua_bindings_manual_files最后面添加manual/pbc/lua_cocos2dx_pbc_manual.cpp、manual/pbc/pbc-lua.c
  • 添加lua文件:把“pbc/binding/lua/protobuf.lua,parser.lua”复制到“src\packages\base”目录下

  • win32和ios下编译:将对应文件加到工程中就行了

  • android编译:上面已经将CMakelist.txt修改好了,直接编译就行。如果需要使用Android.mk编译,需要修改对应的脚本

pbc测试

  • 将“pbc/test/addressbook.proto”拷贝到本地测试目录
  • 生成addressbook.pb,protoc.exe从“https://github.com/protocolbuffers/protobuf/releases”下载最新版本

    1
    protoc.exe --descriptor_set_out=./addressbook.pb addressbook.proto
  • 测试代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    require "packages.base.protobuf"

    --addr = io.open("../../src/test/addressbook.pb","rb")
    --buffer = addr:read "*a"
    --addr:close()

    local filePath = cc.FileUtils:getInstance():fullPathForFilename("test/addressbook.pb")
    local buffer = read_protobuf_file_c(filePath)

    print("---test pbc----------")

    print(filePath..buffer)
    protobuf.register(buffer)

    local t = protobuf.decode("google.protobuf.FileDescriptorSet", buffer)

    local proto = t.file[1]

    print(proto.name)
    print(proto.package)

    local message = proto.message_type

    for _,v in ipairs(message) do
    print(v.name)
    for _,v in ipairs(v.field) do
    print("\t".. v.name .. " ["..v.number.."] " .. v.label)
    end
    end

    local addressbook = {
    name = "Alice",
    id = 12345,
    phone = {
    { number = "1301234567" },
    { number = "87654321", type = "WORK" },
    }
    }

    local code = protobuf.encode("tutorial.Person", addressbook)

    local decode = protobuf.decode("tutorial.Person" , code)

    print(decode.name)
    print(decode.id)
    for _,v in ipairs(decode.phone) do
    print("\t"..v.number, v.type)
    end

    local phonebuf = protobuf.pack("tutorial.Person.PhoneNumber number","87654321")
    local buffer = protobuf.pack("tutorial.Person name id phone", "Alice", 123, { phonebuf })
    print(protobuf.unpack("tutorial.Person name id phone", buffer))

    print("--------------------")

pbc int64 支持

由于lua 51本身不支持int64,所以得先集成一个int64库,github上有蛮多int64库,这次选择了lua-int64,集成方式跟上面类似

  1. lua 51 不支持int64,赋值的时候使用string进行赋值,如“local id=require(“int64”).new_unsigned(“9223372036854775807”)”

修改lua-int64源码,并导出以下接口函数,修改pbc的时候需要用到着两个接口函数

1
2
3
4
5
6
7
LUALIB_API void luaL_i64pushobj(lua_State *L, int64_t n) {
obj64_pushint(L, n);
}

LUALIB_API void luaL_u64pushobj(lua_State *L, uint64_t n) {
obj64_pushunsigned(L, n);
}

修改pbc-lua.c源码

  1. 添加lua-int64头文件

    1
    #include "external/lua/lint64/int64.h"
  2. 读取pb消息修改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    static int
    _rmessage_int64(lua_State *L) {
    struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);
    const char * key = luaL_checkstring(L,2);
    int index = luaL_checkinteger(L,3);
    /*uint32_t v[2];
    v[0] = pbc_rmessage_integer(m, key, index, &v[1]);

    lua_pushlstring(L,(const char *)v,sizeof(v));*/

    uint32_t hi, low;
    low = pbc_rmessage_integer(m, key, index, &hi);
    uint64_t v = (uint64_t)hi << 32 | (uint64_t)low;
    luaL_u64pushobj(L, v);

    return 1;
    }

    static int
    _rmessage_int52(lua_State *L) {
    struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);
    const char * key = luaL_checkstring(L,2);
    int index = luaL_checkinteger(L,3);
    uint32_t hi,low;
    low = pbc_rmessage_integer(m, key, index, &hi);
    int64_t v = (int64_t)((uint64_t)hi << 32 | (uint64_t)low);

    if (hi == 0) {
    lua_pushnumber(L, (lua_Number)v);
    }
    else {
    luaL_i64pushobj(L, v);
    }

    return 1;
    }

    static int
    _rmessage_uint52(lua_State *L) {
    struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);
    const char * key = luaL_checkstring(L,2);
    int index = luaL_checkinteger(L,3);
    uint32_t hi,low;
    low = pbc_rmessage_integer(m, key, index, &hi);
    uint64_t v = (uint64_t)hi << 32 | (uint64_t)low;
    if (hi == 0) {
    lua_pushnumber(L, (lua_Number)v);
    } else {
    luaL_u64pushobj(L, v);
    }

    return 1;
    }
  3. 写入pb消息修改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80

    static int
    _wmessage_int64(lua_State *L) {
    struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);
    const char * key = luaL_checkstring(L,2);

    int isnum;
    uint64_t v64 = luaL_tou64x(L, 3, &isnum);
    if (isnum == 0) {
    return luaL_error(L, "Need an int64 type");
    }

    pbc_wmessage_integer(m, key, (uint32_t)v64, (uint32_t)(v64 >> 32));

    /*switch (lua_type(L,3)) {
    case LUA_TSTRING : {
    size_t len = 0;
    const char * number = lua_tolstring(L,3,&len);
    if (len !=8 ) {
    return luaL_error(L,"Need an 8 length string for int64");
    }
    const uint32_t * v = (const uint32_t *) number;
    pbc_wmessage_integer(m, key, v[0] , v[1]);
    break;
    }
    case LUA_TLIGHTUSERDATA : {
    void * v = lua_touserdata(L,3);
    uint64_t v64 = (uintptr_t)v;
    pbc_wmessage_integer(m, key, (uint32_t)v64 , (uint32_t)(v64>>32));
    break;
    }
    default :
    return luaL_error(L, "Need an int64 type");
    }*/
    return 0;
    }

    static int
    _wmessage_int52(lua_State *L) {
    struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);
    const char * key = luaL_checkstring(L,2);

    int isnum;
    uint64_t v64 = (uint64_t)luaL_toi64x(L, 3, &isnum);
    if (isnum == 0) {
    return luaL_error(L, "Need an int type");
    }

    pbc_wmessage_integer(m, key, (uint32_t)v64, (uint32_t)(v64 >> 32));

    /*int64_t number = (int64_t)(luaL_checknumber(L,3));
    uint32_t hi = (uint32_t)(number >> 32);
    pbc_wmessage_integer(m, key, (uint32_t)number, hi);*/

    return 0;
    }

    static int
    _wmessage_uint52(lua_State *L) {
    struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);
    const char * key = luaL_checkstring(L,2);

    int isnum;
    uint64_t v64 = luaL_tou64x(L, 3, &isnum);
    if (isnum == 0) {
    return luaL_error(L, "Need an uint type");
    }

    pbc_wmessage_integer(m, key, (uint32_t)v64, (uint32_t)(v64 >> 32));

    /*lua_Number v = (luaL_checknumber(L,3));
    if (v < 0) {
    return luaL_error(L, "negative number : %f passed to unsigned field",v);
    }
    uint64_t number = (uint64_t)v;
    uint32_t hi = (uint32_t)(number >> 32);
    pbc_wmessage_integer(m, key, (uint32_t)number, hi);*/

    return 0;
    }
  4. 其他修改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    static void *
    _push_value(lua_State *L, char * ptr, char type) {
    switch(type) {
    case 'u': {
    uint64_t v = *(uint64_t*)ptr;
    ptr += 8;
    //lua_pushnumber(L,(lua_Number)v);
    luaL_u64pushobj(L, v);
    break;
    }
    case 'i': {
    int32_t v = *(int32_t*)ptr;
    ptr += 4;
    lua_pushinteger(L,v);
    break;
    }
    case 'b': {
    int32_t v = *(int32_t*)ptr;
    ptr += 4;
    lua_pushboolean(L,v);
    break;
    }
    case 'p': {
    uint32_t v = *(uint32_t*)ptr;
    ptr += 4;
    lua_pushlightuserdata(L,(void *)(intptr_t)v);
    break;
    }
    case 'x': {
    /*lua_pushlstring(L,ptr,8);
    ptr += 8;*/
    uint64_t v = *(uint64_t*)ptr;
    ptr += 8;
    luaL_u64pushobj(L, v);
    break;
    }
    case 'd': {
    int64_t v = *(int64_t*)ptr;
    ptr += 8;
    //lua_pushnumber(L,(lua_Number)v);
    luaL_i64pushobj(L, v);
    break;
    }
    case 'r': {
    double v = *(double *)ptr;
    ptr += 8;
    lua_pushnumber(L,v);
    break;
    }
    case 's': {
    struct pbc_slice * slice = (struct pbc_slice *)ptr;
    lua_pushlstring(L,(const char *)slice->buffer, slice->len);
    ptr += sizeof(struct pbc_slice);
    break;
    }
    case 'm': {
    struct pbc_slice * slice = (struct pbc_slice *)ptr;
    lua_createtable(L,2,0);
    lua_pushlightuserdata(L, slice->buffer);
    lua_rawseti(L,-2,1);
    lua_pushinteger(L,slice->len);
    lua_rawseti(L,-2,2);
    ptr += sizeof(struct pbc_slice);
    break;
    }
    }
    return ptr;
    }

    static void
    _push_array(lua_State *L, pbc_array array, char type, int index) {
    switch (type) {
    case 'I': {
    int v = pbc_array_integer(array, index, NULL);
    lua_pushinteger(L, v);
    break;
    }
    case 'U': {
    uint32_t hi = 0;
    uint32_t low = pbc_array_integer(array, index, &hi);
    uint64_t v = (uint64_t)hi << 32 | (uint64_t)low;
    //lua_pushnumber(L, (lua_Number)v);
    luaL_u64pushobj(L, v);
    break;
    }
    case 'D': {
    uint32_t hi = 0;
    uint32_t low = pbc_array_integer(array, index, &hi);
    uint64_t v = (uint64_t)hi << 32 | (uint64_t)low;
    //lua_pushnumber(L, (lua_Number)((int64_t)v));
    luaL_i64pushobj(L, v);
    break;
    }
    case 'B': {
    int v = pbc_array_integer(array, index, NULL);
    lua_pushboolean(L, v);
    break;
    }
    case 'P': {
    uint32_t v = pbc_array_integer(array, index, NULL);
    lua_pushlightuserdata(L,(void *)(intptr_t)v);
    break;
    }
    case 'X': {
    uint32_t hi = 0;
    uint32_t low = pbc_array_integer(array, index, &hi);
    uint64_t v = (uint64_t)low | (uint64_t)hi << 32;
    //lua_pushlstring(L, (char *)&v, 8);
    luaL_u64pushobj(L, v);
    break;
    }
    case 'R': {
    double v = pbc_array_real(array, index);
    lua_pushnumber(L, v);
    break;
    }
    case 'S': {
    struct pbc_slice * slice = pbc_array_slice(array, index);
    lua_pushlstring(L, (const char *)slice->buffer,slice->len);
    break;
    }
    case 'M': {
    struct pbc_slice * slice = pbc_array_slice(array, index);
    lua_createtable(L,2,0);
    lua_pushlightuserdata(L,slice->buffer);
    lua_rawseti(L,-2,1);
    lua_pushinteger(L,slice->len);
    lua_rawseti(L,-2,2);
    break;
    }
    }
    lua_rawseti(L,-2,index+1);
    }


    static char *
    _get_value(lua_State *L, int index, char * ptr, char type) {
    switch(type) {
    case 'i': {
    int32_t v = luaL_checkinteger(L, index);
    memcpy(ptr, &v, 4);
    return ptr + 4;
    }
    case 'u': {
    //uint64_t v = (uint64_t)luaL_checknumber(L, index);
    uint64_t v = luaL_tou64x(L, index, NULL);
    memcpy(ptr, &v, 8);
    return ptr + 8;
    }
    case 'd': {
    //int64_t v = (int64_t)luaL_checknumber(L, index);
    int64_t v = luaL_toi64x(L, index, NULL);
    memcpy(ptr, &v, 8);
    return ptr + 8;
    }
    case 'b': {
    int32_t v = lua_toboolean(L, index);
    memcpy(ptr, &v, 4);
    return ptr + 4;
    }
    case 'p': {
    void *p = lua_touserdata(L, index);
    uint32_t v = (uint32_t)(intptr_t)p;
    memcpy(ptr, &v , 4);
    return ptr + 4;
    }
    case 'x': {
    //const char * i64 = luaL_checkstring(L, index);
    uint64_t v = luaL_tou64x(L, index, NULL);
    memcpy(ptr, &v, 8);
    return ptr + 8;
    }
    case 'r': {
    double v = luaL_checknumber(L, index);
    memcpy(ptr, &v, 8);
    return ptr + 8;
    }
    case 's': {
    size_t sz = 0;
    const char * str = luaL_checklstring(L, index, &sz);
    struct pbc_slice * slice = (struct pbc_slice *)ptr;
    slice->buffer = (void*)str;
    slice->len = sz;
    return ptr + sizeof(struct pbc_slice);
    }
    case 'm': {
    struct pbc_slice * slice = (struct pbc_slice *)ptr;
    if (lua_istable(L,index)) {
    lua_rawgeti(L,index,1);
    slice->buffer = lua_touserdata(L,-1);
    lua_rawgeti(L,index,2);
    slice->len = lua_tointeger(L,-1);
    lua_pop(L,2);
    } else {
    size_t sz = 0;
    const char * buffer = luaL_checklstring(L, index, &sz);
    slice->buffer = (void *)buffer;
    slice->len = sz;
    }
    return ptr + sizeof(struct pbc_slice);
    }
    default:
    luaL_error(L,"unknown format %c", type);
    return ptr;
    }
    }

    static void
    _get_array_value(lua_State *L, pbc_array array, char type) {
    switch(type) {
    case 'I': {
    int32_t v = luaL_checkinteger(L, -1);
    uint32_t hi = 0;
    if (v<0) {
    hi = ~0;
    }
    pbc_array_push_integer(array, v, hi);
    break;
    }
    case 'U' : {
    //uint64_t v = (uint64_t)luaL_checknumber(L, -1);
    uint64_t v = luaL_tou64x(L, -1, NULL);
    pbc_array_push_integer(array, (uint32_t)v, (uint32_t)(v >> 32));
    break;
    }
    case 'D' : {
    //int64_t v = (int64_t)luaL_checknumber(L, -1);
    int64_t v = luaL_toi64x(L, -1, NULL);
    pbc_array_push_integer(array, (uint32_t)v, (uint32_t)(v >> 32));
    break;
    }
    case 'B': {
    int32_t v = lua_toboolean(L, -1);
    pbc_array_push_integer(array, v ? 1: 0, 0);
    break;
    }
    case 'P': {
    void *p = lua_touserdata(L, -1);
    uint32_t v = (uint32_t)(intptr_t)p;
    pbc_array_push_integer(array, v, 0);
    break;
    }
    case 'X': {
    //const char * i64 = luaL_checkstring(L, -1);
    //uint64_t v = *(uint64_t *)i64;
    uint64_t v = luaL_tou64x(L, -1, NULL);
    pbc_array_push_integer(array, (uint32_t)v, (uint32_t)(v >> 32));
    break;
    }
    case 'R': {
    double v = luaL_checknumber(L, -1);
    pbc_array_push_real(array, v);
    break;
    }
    case 'S': {
    size_t sz = 0;
    const char * str = luaL_checklstring(L, -1, &sz);
    struct pbc_slice slice;
    slice.buffer = (void*)str;
    slice.len = sz;
    pbc_array_push_slice(array, &slice);
    break;
    }
    case 'M': {
    struct pbc_slice slice;
    if (lua_istable(L,-1)) {
    lua_rawgeti(L,-1,1);
    slice.buffer = lua_touserdata(L,-1);
    lua_rawgeti(L,-2,2);
    slice.len = lua_tointeger(L,-1);
    lua_pop(L,2);
    } else {
    size_t sz = 0;
    const char * buffer = luaL_checklstring(L, -1, &sz);
    slice.buffer = (void *)buffer;
    slice.len = sz;
    }
    pbc_array_push_slice(array, &slice);
    break;
    }
    }
    }


    static void
    push_value(lua_State *L, int type, const char * type_name, union pbc_value *v) {
    switch(type) {
    case PBC_INT:
    lua_pushinteger(L, (int)v->i.low);
    break;
    case PBC_REAL:
    lua_pushnumber(L, v->f);
    break;
    case PBC_BOOL:
    lua_pushboolean(L, v->i.low);
    break;
    case PBC_ENUM:
    lua_pushstring(L, v->e.name);
    break;
    case PBC_BYTES:
    case PBC_STRING:
    lua_pushlstring(L, (const char *)v->s.buffer , v->s.len);
    break;
    case PBC_MESSAGE:
    lua_pushvalue(L, -3);
    lua_pushstring(L, type_name);
    lua_pushlstring(L, (const char *)v->s.buffer , v->s.len);
    lua_call(L, 2 , 1);
    break;
    case PBC_FIXED64: {
    //lua_pushlstring(L, (const char *)&(v->i), 8);
    uint64_t v64 = (uint64_t)(v->i.hi) << 32 | (uint64_t)(v->i.low);
    if (v->i.hi == 0) {
    lua_pushnumber(L, (lua_Number)v64);
    }
    else {
    luaL_u64pushobj(L, v64);
    }
    break;
    }
    case PBC_FIXED32:
    lua_pushlightuserdata(L,(void *)(intptr_t)v->i.low);
    break;
    case PBC_INT64: {
    uint64_t v64 = (uint64_t)(v->i.hi) << 32 | (uint64_t)(v->i.low);
    //lua_pushnumber(L,(lua_Number)(int64_t)v64);
    if (v->i.hi == 0) {
    lua_pushnumber(L, (lua_Number)(int64_t)v64);
    }
    else {
    luaL_i64pushobj(L, (int64_t)v64);
    }
    break;
    }
    case PBC_UINT: {
    uint64_t v64 = (uint64_t)(v->i.hi) << 32 | (uint64_t)(v->i.low);
    if (v->i.hi == 0) {
    lua_pushnumber(L, (lua_Number)v64);
    }
    else {
    luaL_u64pushobj(L, v64);
    }
    //lua_pushnumber(L,(lua_Number)v64);
    break;
    }
    default:
    luaL_error(L, "Unknown type %s", type_name);
    break;
    }
    }

测试:把addressbook.id改成int64,测试代码对应如下修改,输出结果为9223372036854775807LL

1
2
id = "9223372036854775807", -- 修改了pbc底层,会自动序列化成int64格式
-- id = require("int64").new_signed("9223372036854775807"),