├── .gitignore ├── Makefile ├── README.md ├── include ├── LuaPB.h ├── ProtoImporter.h └── Singleton.h ├── src ├── LuaPB.cc └── ProtoImporter.cc └── test └── test1.lua /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | # Flags 4 | CFLAGS =-g -Wall -fpic 5 | LDFLAGS = -shared 6 | 7 | CC?=gcc 8 | CXX?=g++ 9 | LD?=gcc 10 | 11 | # Directories 12 | LUA_INC_DIR ?= /usr/include/lua5.1 13 | PROTOBUF_INC_DIR ?=/usr/local/include 14 | # Files 15 | LIB = luapb.so 16 | 17 | all: 18 | $(CXX) $(CFLAGS) -c -Iinclude -I$(LUA_INC_DIR) -I$(PROTOBUF_INC_DIR) src/*.cc 19 | $(CXX) $(LDFLAGS) -o $(LIB) *.o -L/usr/local/lib -lprotobuf -llua 20 | 21 | clean: 22 | rm -f *.so 23 | rm -f *.o 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | luapb 2 | ===== 3 | 4 | This is a binding of Google Protocol Buffer to Lua -------------------------------------------------------------------------------- /include/LuaPB.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LUAPB_H_ 3 | #define LUAPB_H_ 4 | 5 | #include 6 | #include 7 | 8 | typedef struct tagluamsg 9 | { 10 | google::protobuf::Message* msg; 11 | bool isDelete; //是否要释放掉这个msg; 12 | }lua_pbmsg; 13 | 14 | typedef struct tagluarepeatedmsg 15 | { 16 | google::protobuf::Message* msg; 17 | google::protobuf::FieldDescriptor* field; 18 | }lua_repeated_msg; 19 | 20 | #define PB_MESSAGE "pb" 21 | #define PB_MESSAGE_META "pb_meta" 22 | 23 | #define PB_REPEATED_MESSAGE_META "pb_repeated_meta" 24 | 25 | extern "C" int luaopen_luapb(lua_State* L); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /include/ProtoImporter.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef PROTOIMPORTER_H_ 3 | #define PROTOIMPORTER_H_ 4 | 5 | #include "Singleton.h" 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | class ProtoImporter 13 | { 14 | public: 15 | ProtoImporter(); 16 | public: 17 | bool Import(const std::string& filename); 18 | google::protobuf::Message* createDynamicMessage(const std::string& typeName); 19 | public: 20 | google::protobuf::compiler::Importer importer; 21 | google::protobuf::DynamicMessageFactory factory; 22 | }; 23 | 24 | #define sProtoImporter Singleton::instance() 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /include/Singleton.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef SINGLETON_H 3 | #define SINGLETON_H 4 | 5 | #include 6 | #include // atexit 7 | 8 | template 9 | class Singleton 10 | { 11 | public: 12 | static T& instance() 13 | { 14 | pthread_once(&ponce_, &Singleton::init); 15 | return *value_; 16 | } 17 | 18 | private: 19 | Singleton(); 20 | ~Singleton(); 21 | 22 | static void init() 23 | { 24 | value_ = new T(); 25 | ::atexit(destroy); 26 | } 27 | 28 | static void destroy() 29 | { 30 | delete value_; 31 | } 32 | 33 | private: 34 | static pthread_once_t ponce_; 35 | static T* value_; 36 | }; 37 | 38 | template 39 | pthread_once_t Singleton::ponce_ = PTHREAD_ONCE_INIT; 40 | 41 | template 42 | T* Singleton::value_ = NULL; 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /src/LuaPB.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "LuaPB.h" 3 | #include "ProtoImporter.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace google::protobuf; 14 | 15 | static int push_message(lua_State* L, 16 | Message* message, 17 | bool del) 18 | { 19 | lua_pbmsg* tmp = 20 | static_cast(lua_newuserdata(L, sizeof(lua_pbmsg))); 21 | if (tmp == NULL) 22 | { 23 | return 0; 24 | } 25 | 26 | tmp->msg = message; 27 | tmp->isDelete = del; 28 | 29 | luaL_getmetatable(L, PB_MESSAGE_META); 30 | lua_setmetatable(L, -2); 31 | return 1; 32 | } 33 | 34 | static int push_repeated_msg(lua_State* L, 35 | Message* msg, 36 | FieldDescriptor* field) 37 | { 38 | 39 | lua_repeated_msg* repeated = 40 | static_cast(lua_newuserdata(L, sizeof(lua_repeated_msg))); 41 | 42 | if (!repeated) { 43 | return 0; 44 | } 45 | 46 | repeated->msg = msg; 47 | repeated->field = field; 48 | 49 | luaL_getmetatable(L, PB_REPEATED_MESSAGE_META); 50 | lua_setmetatable(L, -2); 51 | return 1; 52 | } 53 | 54 | static int pb_repeated_add(lua_State* L) 55 | { 56 | lua_repeated_msg* repeated = 57 | (lua_repeated_msg*)luaL_checkudata(L, 1, PB_REPEATED_MESSAGE_META); 58 | 59 | Message* message = repeated->msg; 60 | if (!message) 61 | { 62 | luaL_argerror(L, 1, "pb_repeated_add, pb msg is nil"); 63 | return 0; 64 | } 65 | 66 | FieldDescriptor* field = repeated->field; 67 | const Reflection* reflection = message->GetReflection(); 68 | luaL_argcheck(L, field != NULL, 1, "pb_repeated_add, field is null"); 69 | 70 | if(field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) 71 | { 72 | Message* msg = reflection->AddMessage(message, field); 73 | return push_message(L, msg, false); 74 | } 75 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_INT32) 76 | { 77 | int val = static_cast(luaL_checkinteger(L, 2)); 78 | reflection->AddInt32(message, field, val); 79 | } 80 | else if (field->type() == google::protobuf::FieldDescriptor::TYPE_INT64) 81 | { 82 | long val = static_cast(luaL_checknumber(L, 2)); 83 | reflection->AddInt64(message, field, val); 84 | } 85 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_UINT32) 86 | { 87 | unsigned int val = static_cast(luaL_checknumber(L, 2)); 88 | reflection->AddUInt32(message, field, val); 89 | } 90 | else if (field->type() == google::protobuf::FieldDescriptor::TYPE_UINT64) 91 | { 92 | unsigned long val = static_cast(luaL_checknumber(L, 2)); 93 | reflection->AddUInt64(message, field, val); 94 | } 95 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_FLOAT) 96 | { 97 | float val = static_cast(luaL_checknumber(L, 2)); 98 | reflection->AddFloat(message, field, val); 99 | } 100 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_DOUBLE) 101 | { 102 | double val = static_cast(luaL_checknumber(L, 2)); 103 | reflection->AddDouble(message, field, val); 104 | } 105 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_BOOL) 106 | { 107 | int val = static_cast(luaL_checkinteger(L, 2)); 108 | reflection->AddBool(message, field, val); 109 | } 110 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_STRING) 111 | { 112 | size_t strlen; 113 | const char* str = luaL_checklstring(L, 2, &strlen); 114 | reflection->AddString(message, field, str); 115 | } 116 | else if (field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES) 117 | { 118 | size_t strlen; 119 | const char* str = luaL_checklstring(L, 2, &strlen); 120 | reflection->AddString(message, field, str); 121 | } 122 | else 123 | { 124 | luaL_argerror(L, (2), "pb_repeated_add field name type for add is not support!!"); 125 | } 126 | return 0; 127 | } 128 | 129 | static int pb_repeated_len(lua_State* L) 130 | { 131 | lua_repeated_msg* repeated = 132 | (lua_repeated_msg*)luaL_checkudata(L, 1, PB_REPEATED_MESSAGE_META); 133 | 134 | Message* message = repeated->msg; 135 | if (!message) 136 | { 137 | luaL_argerror(L, 1, "pb_repeated_len, pb msg is nil"); 138 | return 0; 139 | } 140 | 141 | const Reflection* reflection = message->GetReflection(); 142 | FieldDescriptor* field = repeated->field; 143 | luaL_argcheck(L, field != NULL, 1, "pb_repeated_len field not exist"); 144 | 145 | int fieldsize = reflection->FieldSize(*message, field); 146 | lua_pushinteger(L, fieldsize); 147 | return 1; 148 | } 149 | 150 | static int pb_repeated_get(lua_State* L) 151 | { 152 | lua_repeated_msg* repeated = 153 | (lua_repeated_msg*)luaL_checkudata(L, 1, PB_REPEATED_MESSAGE_META); 154 | 155 | Message* message = repeated->msg; 156 | if (!message) 157 | { 158 | luaL_argerror(L, 1, "pb_repeated_get, pb msg is nil"); 159 | return 0; 160 | } 161 | 162 | FieldDescriptor* field = repeated->field; 163 | const Reflection* reflection = message->GetReflection(); 164 | luaL_argcheck(L, field != NULL, 1, "pb_repeated_get field not exist"); 165 | 166 | // -1 为了和lua的下标从一开始保持一致 167 | int index = static_cast(luaL_checkinteger(L, 2)) - 1; 168 | luaL_argcheck(L, index >= 0, 2, "pb_repeated_get index expected >= 1"); 169 | 170 | if(field->type() == google::protobuf::FieldDescriptor::TYPE_INT32) 171 | { 172 | lua_pushinteger(L, reflection->GetRepeatedInt32(*message, field, index)); 173 | } 174 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_STRING) 175 | { 176 | lua_pushstring(L, reflection->GetRepeatedString(*message, field, index).data()); 177 | } 178 | else if (field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES) 179 | { 180 | lua_pushstring(L, reflection->GetRepeatedString(*message, field, index).data()); 181 | } 182 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_UINT32) 183 | { 184 | lua_pushinteger(L, reflection->GetRepeatedUInt32(*message, field, index)); 185 | } 186 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_FLOAT) 187 | { 188 | lua_pushnumber(L, reflection->GetRepeatedFloat(*message, field, index)); 189 | } 190 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_DOUBLE) 191 | { 192 | lua_pushnumber(L, reflection->GetRepeatedDouble(*message, field, index)); 193 | } 194 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_BOOL) 195 | { 196 | lua_pushboolean(L, reflection->GetRepeatedBool(*message, field, index)); 197 | } 198 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) 199 | { 200 | Message* msg = reflection->MutableRepeatedMessage(message, field, index); 201 | return push_message(L, msg, false); 202 | } 203 | else 204 | { 205 | luaL_argerror(L, 0, "pb_repeated_get, field type for get not support!!!"); 206 | return 0; 207 | } 208 | return 1; 209 | } 210 | 211 | static int pb_repeated_set(lua_State* L) 212 | { 213 | lua_repeated_msg* repeated = 214 | (lua_repeated_msg*)luaL_checkudata(L, 1, PB_REPEATED_MESSAGE_META); 215 | 216 | Message* message = repeated->msg; 217 | if (!message) 218 | { 219 | luaL_argerror(L, 1, "pb_repeated_set, pb msg is nil"); 220 | return 0; 221 | } 222 | 223 | const Reflection* reflection = message->GetReflection(); 224 | FieldDescriptor* field = repeated->field; 225 | luaL_argcheck(L, field != NULL, 1, "pb_repeated_set field not exist"); 226 | 227 | int index = static_cast(luaL_checkinteger(L, 2)) - 1; 228 | luaL_argcheck(L, index >= 0, 2, "pb_repeated_set index expected >= 1"); 229 | 230 | if(field->type() == google::protobuf::FieldDescriptor::TYPE_INT32) 231 | { 232 | int val = static_cast(luaL_checkinteger(L, 3)); 233 | reflection->SetRepeatedInt32(message, field, index, val); 234 | } 235 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_UINT32) 236 | { 237 | unsigned int val = static_cast(luaL_checkinteger(L, 3)); 238 | reflection->SetRepeatedUInt32(message, field, index, val); 239 | } 240 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_FLOAT) 241 | { 242 | float val = static_cast(luaL_checknumber(L, 3)); 243 | reflection->SetRepeatedFloat(message, field, index, val); 244 | } 245 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_DOUBLE) 246 | { 247 | double val = static_cast(luaL_checknumber(L, 3)); 248 | reflection->SetRepeatedDouble(message, field, index, val); 249 | } 250 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_BOOL) 251 | { 252 | int val = static_cast(lua_toboolean(L, 3)); 253 | reflection->SetRepeatedBool(message, field, index, val); 254 | } 255 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_STRING) 256 | { 257 | size_t strlen; 258 | const char *str = static_cast(luaL_checklstring(L, 3, &strlen)); 259 | reflection->SetRepeatedString(message, field, index, str); 260 | } 261 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES) 262 | { 263 | size_t strlen; 264 | const char *str = static_cast(luaL_checklstring(L, 3, &strlen)); 265 | reflection->SetRepeatedString(message, field, index, str); 266 | } 267 | else 268 | { 269 | luaL_argerror(L, (2), "pb_repeated_set type for set not support!!!"); 270 | } 271 | return 0; 272 | } 273 | 274 | /////////////////////////////////////////////////////////// 275 | static int pb_import(lua_State* L) 276 | { 277 | const char* filename = luaL_checkstring(L, 1); 278 | sProtoImporter.Import(filename); 279 | return 0; 280 | } 281 | 282 | static int pb_new(lua_State* L) 283 | { 284 | const char* type_name = luaL_checkstring(L, 1); 285 | Message* message = sProtoImporter.createDynamicMessage(type_name); 286 | if (!message) 287 | { 288 | fprintf(stderr, "pb_new error, result is typename(%s) not found!\n", type_name); 289 | return 0; 290 | } 291 | 292 | return push_message(L, message, true); 293 | } 294 | 295 | static int pb_delete(lua_State* L) 296 | { 297 | lua_pbmsg* luamsg = (lua_pbmsg*)luaL_checkudata(L, 1, PB_MESSAGE_META); 298 | 299 | if (luamsg->isDelete && luamsg->msg) 300 | { 301 | Message* message = luamsg->msg; 302 | delete message; 303 | luamsg->msg = NULL; 304 | } 305 | return 0; 306 | } 307 | 308 | static int pb_tostring(lua_State* L) 309 | { 310 | lua_pbmsg* luamsg = (lua_pbmsg*)luaL_checkudata(L, 1, PB_MESSAGE_META); 311 | google::protobuf::Message *message = luamsg->msg; 312 | if (!message) 313 | { 314 | luaL_argerror(L, 1, "pb_tostring, pb msg is nil"); 315 | return 0; 316 | } 317 | std::string msg(message->DebugString()); 318 | lua_pushlstring(L, msg.c_str(), msg.length()); 319 | return 1; 320 | } 321 | 322 | static int pb_get(lua_State* L) 323 | { 324 | lua_pbmsg* luamsg = (lua_pbmsg*)luaL_checkudata(L, 1, PB_MESSAGE_META); 325 | const char* field_name = luaL_checkstring(L, 2); 326 | 327 | Message* message = luamsg->msg; 328 | if (!message) 329 | { 330 | luaL_argerror(L, 1, "pb_get, pb msg is nil"); 331 | return 0; 332 | } 333 | 334 | const Descriptor* descriptor = message->GetDescriptor(); 335 | const Reflection* reflection = message->GetReflection(); 336 | const FieldDescriptor* field = descriptor->FindFieldByName(field_name); 337 | luaL_argcheck(L, (field != NULL), 2, "pb_get, field_name error"); 338 | 339 | if (field->is_repeated()) 340 | { 341 | return push_repeated_msg(L, message, const_cast(field)); 342 | } 343 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_INT32) 344 | { 345 | lua_pushinteger(L, reflection->GetInt32(*message, field)); 346 | } 347 | else if (field->type() == google::protobuf::FieldDescriptor::TYPE_INT64) 348 | { 349 | lua_pushnumber(L, reflection->GetInt64(*message, field)); 350 | } 351 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_UINT32) 352 | { 353 | lua_pushinteger(L, reflection->GetUInt32(*message, field)); 354 | } 355 | else if (field->type() == google::protobuf::FieldDescriptor::TYPE_UINT64) 356 | { 357 | lua_pushnumber(L, reflection->GetUInt64(*message, field)); 358 | } 359 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_FLOAT) 360 | { 361 | lua_pushnumber(L, reflection->GetFloat(*message, field)); 362 | } 363 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_DOUBLE) 364 | { 365 | lua_pushnumber(L, reflection->GetDouble(*message, field)); 366 | } 367 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_BOOL) 368 | { 369 | lua_pushboolean(L, reflection->GetBool(*message, field)); 370 | } 371 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_STRING) 372 | { 373 | std::string str(reflection->GetString(*message, field)); 374 | lua_pushlstring(L, str.c_str(), str.length()); 375 | } 376 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES) 377 | { 378 | std::string str(reflection->GetString(*message, field)); 379 | lua_pushlstring(L, str.c_str(), str.length()); 380 | } 381 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) 382 | { 383 | Message* msg = reflection->MutableMessage(message, field); 384 | return push_message(L, msg, false); 385 | } 386 | return 1; 387 | } 388 | 389 | static int pb_set(lua_State* L) 390 | { 391 | lua_pbmsg* luamsg = (lua_pbmsg*)luaL_checkudata(L, 1, PB_MESSAGE_META); 392 | const char* field_name = luaL_checkstring(L, 2); 393 | 394 | Message* message = luamsg->msg; 395 | if (!message) 396 | { 397 | luaL_argerror(L, 1, "pb_set, pb msg is nil"); 398 | return 0; 399 | } 400 | 401 | const Descriptor* descriptor = message->GetDescriptor(); 402 | const Reflection* reflection = message->GetReflection(); 403 | const FieldDescriptor* field = descriptor->FindFieldByName(field_name); 404 | 405 | luaL_argcheck(L, field != NULL, 2, "LuaPB::set field_name error"); 406 | luaL_argcheck(L, !field->is_repeated(), 2, "LuaPB::set field_name is repeated"); 407 | 408 | if(field->type() == google::protobuf::FieldDescriptor::TYPE_STRING) 409 | { 410 | size_t strlen; 411 | const char *str = luaL_checklstring(L, 3, &strlen); 412 | reflection->SetString(message, field, str); 413 | } 414 | else if (field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES) 415 | { 416 | size_t strlen; 417 | const char *str = luaL_checklstring(L, 3, &strlen); 418 | reflection->SetString(message, field, str); 419 | } 420 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_INT32) 421 | { 422 | int val = static_cast(luaL_checkinteger(L, 3)); 423 | reflection->SetInt32(message, field, val); 424 | } 425 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_INT64) 426 | { 427 | long val = static_cast(luaL_checknumber(L, 3)); 428 | reflection->SetInt64(message, field, val); 429 | } 430 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_UINT32) 431 | { 432 | unsigned int val = static_cast(luaL_checkinteger(L, 3)); 433 | reflection->SetUInt32(message, field, val); 434 | } 435 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_UINT64) 436 | { 437 | unsigned long val = static_cast(luaL_checknumber(L, 3)); 438 | reflection->SetUInt64(message, field, val); 439 | } 440 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_FLOAT) 441 | { 442 | float val = static_cast(luaL_checknumber(L, 3)); 443 | reflection->SetFloat(message, field, val); 444 | } 445 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_DOUBLE) 446 | { 447 | double val = static_cast(luaL_checknumber(L, 3)); 448 | reflection->SetDouble(message, field, val); 449 | } 450 | else if(field->type() == google::protobuf::FieldDescriptor::TYPE_BOOL) 451 | { 452 | int val = static_cast(luaL_checkinteger(L, 3)); 453 | reflection->SetBool(message, field, val); 454 | } 455 | else 456 | { 457 | luaL_argerror(L, 2, "pb_set field_name type error"); 458 | } 459 | return 0; 460 | } 461 | 462 | static int pb_parseFromString(lua_State* L) 463 | { 464 | lua_pbmsg* luamsg = (lua_pbmsg*)luaL_checkudata(L, 1, PB_MESSAGE_META); 465 | Message* message = luamsg->msg; 466 | 467 | luaL_checktype(L, 2, LUA_TSTRING); 468 | 469 | size_t bin_len; 470 | const char* bin = static_cast( luaL_checklstring(L, 2, &bin_len)); 471 | message->ParseFromArray(bin, bin_len); 472 | return 0; 473 | } 474 | 475 | static int pb_serializeToString(lua_State* L) 476 | { 477 | lua_pbmsg* luamsg = (lua_pbmsg*)luaL_checkudata(L, 1, PB_MESSAGE_META); 478 | Message* message = luamsg->msg; 479 | 480 | std::string msg; 481 | message->SerializeToString(&msg); 482 | lua_pushlstring(L, msg.c_str(), msg.length()); 483 | return 1; 484 | } 485 | 486 | static const struct luaL_reg lib[] = 487 | { 488 | {"new", pb_new}, 489 | {"import", pb_import}, 490 | {"tostring", pb_tostring}, 491 | {"parseFromString", pb_parseFromString}, 492 | {"serializeToString", pb_serializeToString}, 493 | {NULL, NULL} 494 | }; 495 | 496 | static const struct luaL_reg libm[] = 497 | { 498 | {"__index", pb_get}, 499 | {"__newindex", pb_set}, 500 | {"__gc", pb_delete}, 501 | {NULL, NULL} 502 | }; 503 | 504 | static const struct luaL_reg repeatedlib[] = { 505 | {"add", pb_repeated_add}, 506 | {"len", pb_repeated_len}, 507 | {"get", pb_repeated_get}, 508 | {"set", pb_repeated_set}, 509 | {NULL, NULL}, 510 | }; 511 | 512 | int luaopen_luapb(lua_State* L) 513 | { 514 | luaL_newmetatable(L, PB_REPEATED_MESSAGE_META); 515 | luaL_register(L, NULL, repeatedlib); 516 | 517 | lua_pushstring(L, "__index"); 518 | lua_pushvalue(L, -2); 519 | lua_settable(L, -3); 520 | 521 | lua_pushstring(L, "__newindex"); 522 | lua_pushcfunction(L, pb_repeated_set); 523 | lua_settable(L, -3); 524 | 525 | luaL_newmetatable(L, PB_MESSAGE_META); 526 | luaL_register(L, NULL, libm); 527 | 528 | luaL_register(L, PB_MESSAGE, lib); 529 | return 1; 530 | } 531 | 532 | 533 | -------------------------------------------------------------------------------- /src/ProtoImporter.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "ProtoImporter.h" 3 | 4 | #include 5 | 6 | class MyMultiFileErrorCollector : public google::protobuf::compiler::MultiFileErrorCollector 7 | { 8 | virtual void AddError( 9 | const std::string & filename, 10 | int line, 11 | int column, 12 | const std::string & message) 13 | { 14 | fprintf(stderr, "%s:%d:%d:%s\n", filename.c_str(), line, column, message.c_str()); 15 | } 16 | }; 17 | 18 | static MyMultiFileErrorCollector errorCollector; 19 | static google::protobuf::compiler::DiskSourceTree sourceTree; 20 | 21 | ProtoImporter::ProtoImporter(): 22 | importer(&sourceTree, &errorCollector) 23 | { 24 | char* protopath = getenv("PROTO_PATH"); 25 | if (!protopath) 26 | { 27 | sourceTree.MapPath("", ""); 28 | } 29 | else 30 | { 31 | sourceTree.MapPath("", protopath); 32 | } 33 | printf("[ProtoImporter] protopath:%s\n", protopath); 34 | } 35 | 36 | bool ProtoImporter::Import(const std::string& filename) 37 | { 38 | const google::protobuf::FileDescriptor* filedescriptor = importer.Import(filename); 39 | if (!filedescriptor) 40 | { 41 | fprintf(stderr, "import (%s) file descriptor error\n", filename.c_str()); 42 | return false; 43 | } 44 | return true; 45 | } 46 | 47 | google::protobuf::Message* ProtoImporter::createDynamicMessage(const std::string& typeName) 48 | { 49 | google::protobuf::Message* message = NULL; 50 | const google::protobuf::Descriptor* descriptor = importer.pool()->FindMessageTypeByName(typeName); 51 | if (descriptor) 52 | { 53 | const google::protobuf::Message* prototype = factory.GetPrototype(descriptor); 54 | if (prototype) 55 | { 56 | message = prototype->New(); 57 | } 58 | } 59 | return message; 60 | } 61 | -------------------------------------------------------------------------------- /test/test1.lua: -------------------------------------------------------------------------------- 1 | require("luapb"); 2 | 3 | --package lm; 4 | --message test 5 | --{ 6 | -- required int32 uid = 1; 7 | -- required int32 param = 2; 8 | -- optional string param1 = 3; 9 | -- repeated string param2 = 4; 10 | --}; 11 | 12 | pb.import("test.proto"); 13 | 14 | 15 | local msg = pb.new("lm.test"); 16 | msg.uid = 12345; 17 | msg.param = 9876; 18 | msg.param1 = "zjx"; 19 | --print("type: " .. type(msg.param2)); 20 | msg.param2:add("first"); 21 | msg.param2:add("second"); 22 | msg.param2:add("three"); 23 | 24 | print("uid: " .. msg.uid); 25 | print("param: " .. msg.param); 26 | print("param1: " .. msg.param1); 27 | 28 | 29 | for i = 1, msg.param2:len() do 30 | local value = msg.param2:get(i); 31 | print("i: " .. i .. " value: " .. value); 32 | end 33 | 34 | msg.param2[1] = "test" 35 | print("===== param2: " .. msg.param2:get(1)) 36 | 37 | msg.param2:set(2, "test2") 38 | print("===== param2: " .. msg.param2:get(2)) 39 | 40 | 41 | print("str: " .. pb.tostring(msg)); 42 | 43 | --------------------------------------------------------------------------------