├── .gitignore ├── Makefile ├── README.md ├── debug_test.cpp ├── debug_test.lua ├── debughelper.cpp ├── debughelper.h ├── reg_test.cpp ├── reg_test.lua └── reghelper.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | lua.h 3 | luaconf.h 4 | lualib.h 5 | lauxlib.h -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # makefile for lua helper 2 | # build on mac os, gcc 4.2.1 3 | 4 | CC=g++ 5 | RM=rm 6 | 7 | CFLAGS= -O2 8 | LUA=-llua -L. 9 | 10 | all: 11 | $(CC) -o debug_test.out debug_test.cpp debughelper.cpp $(CFLAGS) $(LUA) 12 | $(CC) -o reg_test.out reg_test.cpp $(CFLAGS) $(LUA) 13 | 14 | clean: 15 | $(RM) -rf *.o *.out -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | some tools for writing lua code. 2 | test on lua 5.2, mac os x, gcc 4.2.1. 3 | -------------------------------------------------------------------------------- /debug_test.cpp: -------------------------------------------------------------------------------- 1 | #include "debughelper.h" 2 | 3 | extern "C"{ 4 | #include "lua.h" 5 | #include "lauxlib.h" 6 | #include "lualib.h" 7 | } 8 | 9 | int main() 10 | { 11 | lua_State* pState = luaL_newstate(); 12 | luaL_openlibs(pState); 13 | 14 | CDebugHelper::inst().regDebug(pState); 15 | 16 | luaL_loadfile(pState, "debug_test.lua"); 17 | lua_pcall(pState, 0, LUA_MULTRET, 0); 18 | 19 | CDebugHelper::inst().unRegDebug(pState); 20 | 21 | lua_close(pState); 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /debug_test.lua: -------------------------------------------------------------------------------- 1 | function fun1() 2 | local a = 10 3 | local b = 11 4 | local c = a + b 5 | function inner() 6 | local d = a + b 7 | db() 8 | end 9 | inner() 10 | return c 11 | end 12 | 13 | function fun2() 14 | fun1() 15 | end 16 | 17 | function fun3() 18 | fun2() 19 | end 20 | 21 | g = {} 22 | g[10] = 10 23 | g["10"] = 11 24 | g.a = 12 25 | 26 | print(g["10"]) 27 | 28 | db() 29 | fun3() 30 | 31 | -------------------------------------------------------------------------------- /debughelper.cpp: -------------------------------------------------------------------------------- 1 | #include "debughelper.h" 2 | 3 | extern "C" 4 | { 5 | #include "lua.h" 6 | #include "lauxlib.h" 7 | #include "lualib.h" 8 | } 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | CDebugHelper::CDebugHelper() 17 | { 18 | } 19 | 20 | CDebugHelper::~CDebugHelper() 21 | { 22 | } 23 | 24 | void CDebugHelper::regDebug(lua_State* pState) 25 | { 26 | lua_pushcclosure(pState, CDebugHelper::debug, 0); 27 | lua_setglobal(pState, "db"); 28 | 29 | setNoneHook(pState); 30 | 31 | lua_sethook(pState, CDebugHelper::debugHook, LUA_MASKLINE | LUA_MASKRET | LUA_MASKCALL, 0); 32 | } 33 | 34 | void CDebugHelper::unRegDebug(lua_State* pState) 35 | { 36 | lua_pushnil(pState); 37 | lua_setglobal(pState, "db"); 38 | } 39 | 40 | int CDebugHelper::debug(lua_State* pState) 41 | { 42 | if (!CDebugHelper::inst().checkNoneHook()) 43 | { 44 | return 0; 45 | } 46 | 47 | CDebugHelper::inst().run(pState); 48 | return 0; 49 | } 50 | 51 | int CDebugHelper::checkNoneHook() 52 | { 53 | return m_hook == &CDebugHelper::noneHook; 54 | } 55 | 56 | void CDebugHelper::debugHook(lua_State* pState, lua_Debug* ar) 57 | { 58 | CDebugHelper::inst().callHook(pState, ar); 59 | } 60 | 61 | void CDebugHelper::callHook(lua_State* pState, lua_Debug* ar) 62 | { 63 | (this->*m_hook)(pState, ar); 64 | } 65 | 66 | void CDebugHelper::setNoneHook(lua_State* pState) 67 | { 68 | m_hook = &CDebugHelper::noneHook; 69 | m_curStackDepth = -1; 70 | } 71 | 72 | void CDebugHelper::setReturnHook(lua_State* pState) 73 | { 74 | m_hook = &CDebugHelper::returnHook; 75 | m_curStackDepth = getStackDepth(pState); 76 | } 77 | 78 | void CDebugHelper::setNextHook(lua_State* pState) 79 | { 80 | m_hook = &CDebugHelper::nextHook; 81 | m_curStackDepth = getStackDepth(pState); 82 | } 83 | 84 | void CDebugHelper::setStepHook(lua_State* pState) 85 | { 86 | m_hook = &CDebugHelper::stepHook; 87 | m_curStackDepth = -1; 88 | } 89 | 90 | void CDebugHelper::noneHook(lua_State* pState, lua_Debug* ar) 91 | { 92 | (void)pState; 93 | (void)ar; 94 | } 95 | 96 | void CDebugHelper::returnHook(lua_State* pState, lua_Debug* ar) 97 | { 98 | if(ar->event != LUA_HOOKRET) 99 | { 100 | return; 101 | } 102 | 103 | int curStackDepth = getStackDepth(pState); 104 | if(m_curStackDepth < curStackDepth) 105 | { 106 | return; 107 | } 108 | 109 | printLine(pState); 110 | return run(pState); 111 | } 112 | 113 | void CDebugHelper::nextHook(lua_State* pState, lua_Debug* ar) 114 | { 115 | if(ar->event != LUA_HOOKLINE) 116 | { 117 | return; 118 | } 119 | 120 | int curStackDepth = getStackDepth(pState); 121 | if(m_curStackDepth < curStackDepth) 122 | { 123 | return; 124 | } 125 | 126 | printLine(pState); 127 | return run(pState); 128 | } 129 | 130 | void CDebugHelper::stepHook(lua_State* pState, lua_Debug* ar) 131 | { 132 | if(ar->event != LUA_HOOKLINE) 133 | { 134 | return; 135 | } 136 | 137 | printLine(pState); 138 | return run(pState); 139 | } 140 | 141 | void CDebugHelper::run(lua_State* pState) 142 | { 143 | char buffer[1024]; 144 | 145 | char sep[] = " \t\n"; 146 | char* next = NULL; 147 | char* last = NULL; 148 | char* cmd = NULL; 149 | 150 | m_curFrame = 0; 151 | 152 | while(true) 153 | { 154 | printf("(db): "); 155 | fgets(buffer, 1024, stdin); 156 | 157 | if(buffer[0] == '\0') 158 | { 159 | if(m_lastCmd[0] == '\0') 160 | { 161 | continue; 162 | } 163 | else 164 | { 165 | strcpy(buffer, m_lastCmd); 166 | } 167 | } 168 | else 169 | { 170 | strcpy(m_lastCmd, buffer); 171 | } 172 | 173 | next = strtok_r(buffer, sep, &last); 174 | cmd = next; 175 | 176 | for(char* p = cmd; *p; ++p) 177 | { 178 | *p = tolower(*p); 179 | } 180 | 181 | if(strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0) 182 | { 183 | help(); 184 | continue; 185 | } 186 | else if(strcmp(cmd, "c") == 0 || strcmp(cmd, "continue") == 0) 187 | { 188 | setNoneHook(pState); 189 | return; 190 | } 191 | else if(strcmp(cmd, "bt") == 0) 192 | { 193 | printBacktrace(pState); 194 | continue; 195 | } 196 | else if(strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0) 197 | { 198 | int beginLine = 0; 199 | int endLine = 0; 200 | next = strtok_r(NULL, sep, &last); 201 | if (next) 202 | { 203 | beginLine = atoi(next); 204 | next = strtok_r(NULL, sep, &last); 205 | if (next) 206 | { 207 | endLine = atoi(next); 208 | } 209 | } 210 | 211 | printSource(pState, beginLine, endLine); 212 | } 213 | else if(strcmp(cmd, "f") == 0 || strcmp(cmd, "frame") == 0) 214 | { 215 | next = strtok_r(NULL, sep, &last); 216 | if(next) 217 | { 218 | m_curFrame = atoi(next); 219 | } 220 | printFrame(pState, m_curFrame); 221 | continue; 222 | } 223 | else if(strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0) 224 | { 225 | next = strtok_r(NULL, sep, &last); 226 | if (next) 227 | { 228 | printValue(pState, next); 229 | } 230 | 231 | continue; 232 | } 233 | else if(strcmp(cmd, "n") == 0 || strcmp(cmd, "next") == 0) 234 | { 235 | setNextHook(pState); 236 | return; 237 | } 238 | else if(strcmp(cmd, "s") == 0 || strcmp(cmd, "step") == 0) 239 | { 240 | setStepHook(pState); 241 | return; 242 | } 243 | else if(strcmp(cmd, "return") == 0) 244 | { 245 | setReturnHook(pState); 246 | return; 247 | } 248 | } 249 | } 250 | 251 | void CDebugHelper::help() 252 | { 253 | const char* msg = "" 254 | "Lua Debuger Help: \n\n" 255 | "h/help: Show Help Infomation\n" 256 | "c/continue Continue the program until quit or reach another break\n" 257 | "bt Show backtrace\n" 258 | "l/list s e list source from line s to e\n" 259 | "f/frame n Show a frame, n is the frame level\n"; 260 | "p/print value Print the value\n"; 261 | "n/next Step program, proceeding through subroutine calls\n"; 262 | "s/step Step program until it reaches a different source line\n"; 263 | "return Run the function until it's return\n"; 264 | "\n"; 265 | 266 | printf("%s", msg); 267 | } 268 | 269 | int CDebugHelper::getStackDepth(lua_State* pState) 270 | { 271 | int depth = 0; 272 | lua_Debug ar; 273 | while(lua_getstack(pState, depth, &ar)) 274 | { 275 | depth++; 276 | } 277 | return depth; 278 | } 279 | 280 | void CDebugHelper::printLine(lua_State* pState) 281 | { 282 | lua_Debug ar; 283 | if(!lua_getstack(pState, m_curFrame, &ar)) 284 | { 285 | printf("no source info\n"); 286 | return; 287 | } 288 | 289 | lua_getinfo(pState, "nSl", &ar); 290 | int line = ar.currentline; 291 | if (line == -1) 292 | { 293 | printf("No Source Info\n"); 294 | return; 295 | } 296 | 297 | const char* source =ar.source; 298 | if(source[0] == '@') 299 | { 300 | const char* fileName = ++source; 301 | FILE* fp = fopen(fileName, "r"); 302 | if(!fp) 303 | { 304 | printf("can not open %s\n", fileName); 305 | return; 306 | } 307 | 308 | int i = 1; 309 | char buffer[1024]; 310 | while(fgets(buffer, 1024, fp)) 311 | { 312 | if(i == line) 313 | { 314 | int len = strlen(buffer); 315 | if(buffer[len - 1] == '\r' || buffer[len - 1] == '\n') 316 | { 317 | buffer[len - 1] = '\0'; 318 | } 319 | printf("%s\n", buffer); 320 | break; 321 | } 322 | i++; 323 | } 324 | 325 | fclose(fp); 326 | } 327 | } 328 | 329 | void CDebugHelper::printBacktrace(lua_State* pState) 330 | { 331 | int depth = getStackDepth(pState); 332 | for (int i = 0; i < depth; ++i) 333 | { 334 | printFrame(pState, i); 335 | } 336 | } 337 | 338 | void CDebugHelper::printSource(lua_State* pState, int beginLine, int endLine) 339 | { 340 | lua_Debug ar; 341 | if(!lua_getstack(pState, m_curFrame, &ar)) 342 | { 343 | printf("no source info\n"); 344 | return; 345 | } 346 | 347 | lua_getinfo(pState, "nSl", &ar); 348 | int line = ar.currentline; 349 | if (line == -1) 350 | { 351 | printf("No Source Info\n"); 352 | return; 353 | } 354 | 355 | if (beginLine >= endLine) 356 | { 357 | beginLine = line - 5; 358 | endLine = line + 5; 359 | } 360 | 361 | if (beginLine < 0) 362 | { 363 | beginLine = 0; 364 | } 365 | 366 | const char* source =ar.source; 367 | if(source[0] == '@') 368 | { 369 | const char* fileName = ++source; 370 | FILE* fp = fopen(fileName, "r"); 371 | if(!fp) 372 | { 373 | printf("can not open %s\n", fileName); 374 | return; 375 | } 376 | 377 | int i = 1; 378 | char buffer[1024]; 379 | while(fgets(buffer, 1024, fp)) 380 | { 381 | if(i >= beginLine and i <= endLine) 382 | { 383 | int len = strlen(buffer); 384 | if(buffer[len - 1] == '\r' || buffer[len - 1] == '\n') 385 | { 386 | buffer[len - 1] = '\0'; 387 | } 388 | printf("%04d:%s\n", i, buffer); 389 | } 390 | if (i > endLine) 391 | { 392 | break; 393 | } 394 | i++; 395 | } 396 | 397 | fclose(fp); 398 | } 399 | 400 | } 401 | 402 | void CDebugHelper::printFrame(lua_State* pState, int frame) 403 | { 404 | lua_Debug ar; 405 | if(!lua_getstack(pState, frame, &ar)) 406 | { 407 | return; 408 | } 409 | 410 | lua_getinfo(pState, "nSl", &ar); 411 | 412 | char buffer[1024]; 413 | 414 | char* p = buffer; 415 | 416 | int len = sprintf(p, "%d ", frame); 417 | p += len; 418 | 419 | if(ar.name) 420 | { 421 | len = sprintf(p, "%s ", ar.name); 422 | p += len; 423 | } 424 | else 425 | { 426 | if(ar.what) 427 | { 428 | len = sprintf(p, "%s ", ar.what); 429 | p += len; 430 | } 431 | } 432 | 433 | if (ar.source) 434 | { 435 | len = sprintf(p, "%s", ar.source); 436 | p += len; 437 | } 438 | 439 | sprintf(p, ":%d", ar.currentline); 440 | 441 | printf("%s\n", buffer); 442 | } 443 | 444 | void CDebugHelper::printValue(lua_State* pState, const char* value) 445 | { 446 | char buffer[1024]; 447 | int top = lua_gettop(pState); 448 | 449 | char sep[] = ".[]"; 450 | char* next = NULL; 451 | char* last = NULL; 452 | 453 | bool found = false; 454 | 455 | strcpy(buffer, value); 456 | 457 | lua_Debug ar; 458 | lua_getstack(pState, m_curFrame, &ar); 459 | 460 | next = strtok_r(buffer, sep, &last); 461 | 462 | do 463 | { 464 | for(int i = 1;;i++) 465 | { 466 | const char* key = lua_getlocal(pState, &ar, i); 467 | if(!key) 468 | { 469 | break; 470 | } 471 | 472 | if(strcmp(key, next) == 0) 473 | { 474 | found = true; 475 | break; 476 | } 477 | else 478 | { 479 | lua_pop(pState, 1); 480 | } 481 | } 482 | 483 | if (found) 484 | { 485 | break; 486 | } 487 | 488 | lua_getinfo(pState, "f", &ar); 489 | int funcIndex = lua_gettop(pState); 490 | for (int i = 1; ; i++) 491 | { 492 | const char* key = lua_getupvalue(pState, funcIndex, i); 493 | if (!key) 494 | { 495 | break; 496 | } 497 | 498 | if (strcmp(key, next) == 0) 499 | { 500 | found = true; 501 | break; 502 | } 503 | else 504 | { 505 | lua_pop(pState, 1); 506 | } 507 | } 508 | 509 | if (found) 510 | { 511 | break; 512 | } 513 | 514 | lua_getglobal(pState, next); 515 | if (lua_isnil(pState, -1)) 516 | { 517 | lua_pop(pState, 1); 518 | } 519 | else 520 | { 521 | found = true; 522 | } 523 | }while(0); 524 | 525 | if (!found) 526 | { 527 | printf("nil value\n"); 528 | } 529 | else 530 | { 531 | while(true) 532 | { 533 | if (lua_isnil(pState, -1)) 534 | { 535 | printf("nil value\n"); 536 | break; 537 | } 538 | next = strtok_r(NULL, sep, &last); 539 | if(!next) 540 | { 541 | printStackValue(pState, -1); 542 | break; 543 | } 544 | else 545 | { 546 | bool isNumber = true; 547 | int len = strlen(next); 548 | for (int i = 0; i < len; ++i) 549 | { 550 | if (!isdigit(next[i])) 551 | { 552 | isNumber = false; 553 | break; 554 | } 555 | } 556 | 557 | if (isNumber) 558 | { 559 | lua_pushnumber(pState, atoi(next)); 560 | } 561 | else 562 | { 563 | if(next[0] == '"' && next[len - 1] == '"') 564 | { 565 | next[len - 1] = '\0'; 566 | lua_pushstring(pState, next + 1); 567 | } 568 | else 569 | { 570 | lua_pushstring(pState, next); 571 | } 572 | } 573 | 574 | lua_gettable(pState, -2); 575 | continue; 576 | } 577 | } 578 | } 579 | 580 | lua_settop(pState, top); 581 | } 582 | 583 | void CDebugHelper::printStackValue(lua_State* pState, int index) 584 | { 585 | int type = lua_type(pState, index); 586 | switch(type) 587 | { 588 | case LUA_TNUMBER: 589 | printf("%g\n", lua_tonumber(pState, index)); 590 | break; 591 | case LUA_TSTRING: 592 | printf("%s\n", lua_tostring(pState, index)); 593 | break; 594 | case LUA_TBOOLEAN: 595 | printf("%d\n", int(lua_toboolean(pState, index))); 596 | break; 597 | case LUA_TTABLE: 598 | printTable(pState, index); 599 | break; 600 | case LUA_TTHREAD: 601 | case LUA_TFUNCTION: 602 | case LUA_TUSERDATA: 603 | case LUA_TLIGHTUSERDATA: 604 | printf("%s:%p\n", lua_typename(pState, type), lua_topointer(pState, -1)); 605 | break; 606 | default: 607 | printf("nil value\n"); 608 | break; 609 | } 610 | } 611 | 612 | void CDebugHelper::printTable(lua_State* pState, int index) 613 | { 614 | int top = lua_gettop(pState); 615 | 616 | lua_pushvalue(pState, index); 617 | 618 | fprintf(stdout, "{\n"); 619 | 620 | lua_pushnil(pState); 621 | 622 | while(lua_next(pState, -2)) 623 | { 624 | fprintf(stdout, "\t"); 625 | int type = lua_type(pState, -2); 626 | switch(type) 627 | { 628 | case LUA_TNUMBER: 629 | fprintf(stdout, "%g", lua_tonumber(pState, -2)); 630 | break; 631 | case LUA_TBOOLEAN: 632 | fprintf(stdout, "%d", int(lua_toboolean(pState, -2))); 633 | break; 634 | case LUA_TSTRING: 635 | fprintf(stdout, "%s", lua_tostring(pState, -2)); 636 | break; 637 | default: 638 | fprintf(stdout, "%s:%p", lua_typename(pState, type), lua_topointer(pState, -2)); 639 | break; 640 | } 641 | 642 | fprintf(stdout, "\t\t=\t"); 643 | 644 | type = lua_type(pState, -1); 645 | switch(type) 646 | { 647 | case LUA_TNUMBER: 648 | fprintf(stdout, "%g", lua_tonumber(pState, -1)); 649 | break; 650 | case LUA_TBOOLEAN: 651 | fprintf(stdout, "%d", int(lua_toboolean(pState, -1))); 652 | break; 653 | case LUA_TSTRING: 654 | fprintf(stdout, "%s", lua_tostring(pState, -1)); 655 | break; 656 | default: 657 | fprintf(stdout, "%s:%p", lua_typename(pState, type), lua_topointer(pState, -1)); 658 | break; 659 | } 660 | 661 | fprintf(stdout, "\n"); 662 | 663 | lua_pop(pState, 1); 664 | } 665 | 666 | fprintf(stdout, "}\n"); 667 | 668 | lua_settop(pState, top); 669 | } 670 | 671 | 672 | -------------------------------------------------------------------------------- /debughelper.h: -------------------------------------------------------------------------------- 1 | #ifndef debughelper_h 2 | #define debughelper_h 3 | 4 | struct lua_State; 5 | struct lua_Debug; 6 | 7 | class CDebugHelper 8 | { 9 | public: 10 | static CDebugHelper& inst() 11 | { 12 | static CDebugHelper helper; 13 | return helper; 14 | } 15 | 16 | void regDebug(lua_State* pState); 17 | void unRegDebug(lua_State* pState); 18 | 19 | static int debug(lua_State* pState); 20 | static void debugHook(lua_State* pState, lua_Debug* ar); 21 | 22 | private: 23 | CDebugHelper(); 24 | ~CDebugHelper(); 25 | 26 | void callHook(lua_State* pState, lua_Debug* ar); 27 | void noneHook(lua_State* state, lua_Debug* ar); 28 | void returnHook(lua_State* state, lua_Debug* ar); 29 | void nextHook(lua_State* state, lua_Debug* ar); 30 | void stepHook(lua_State* state, lua_Debug* ar); 31 | 32 | void setNoneHook(lua_State* state); 33 | void setReturnHook(lua_State* state); 34 | void setNextHook(lua_State* state); 35 | void setStepHook(lua_State* state); 36 | 37 | void run(lua_State* pState); 38 | int checkNoneHook(); 39 | 40 | void help(); 41 | int getStackDepth(lua_State* pState); 42 | 43 | void printLine(lua_State* pState); 44 | void printBacktrace(lua_State* pState); 45 | void printSource(lua_State* pState, int beginLine, int endLine); 46 | void printFrame(lua_State* pState, int frame); 47 | void printValue(lua_State* pState, const char* value); 48 | 49 | void printStackValue(lua_State* pState, int index); 50 | void printTable(lua_State* pState, int index); 51 | 52 | private: 53 | typedef void (CDebugHelper::*hookFunc)(lua_State* state, lua_Debug* ar); 54 | 55 | hookFunc m_hook; 56 | int m_curStackDepth; 57 | int m_curFrame; 58 | 59 | char m_lastCmd[1024]; 60 | char m_curCmd[1024]; 61 | }; 62 | 63 | 64 | #endif -------------------------------------------------------------------------------- /reg_test.cpp: -------------------------------------------------------------------------------- 1 | extern "C"{ 2 | #include "lua.h" 3 | #include "lauxlib.h" 4 | #include "lualib.h" 5 | } 6 | 7 | #include "reghelper.h" 8 | 9 | 10 | int test0() 11 | { 12 | return 0; 13 | } 14 | 15 | int test1(int a) 16 | { 17 | return a; 18 | } 19 | 20 | int test2(int a, int b) 21 | { 22 | return a - b; 23 | } 24 | 25 | const char* test3(const char* str) 26 | { 27 | return str; 28 | } 29 | 30 | void test4() 31 | { 32 | 33 | } 34 | 35 | int main() 36 | { 37 | lua_State* pState = luaL_newstate(); 38 | luaL_openlibs(pState); 39 | 40 | REGISTER_FUNCTION(pState, test0); 41 | REGISTER_FUNCTION(pState, test1); 42 | REGISTER_FUNCTION(pState, test2); 43 | REGISTER_FUNCTION(pState, test3); 44 | REGISTER_FUNCTION(pState, test4); 45 | 46 | luaL_loadfile(pState, "reg_test.lua"); 47 | lua_pcall(pState, 0, LUA_MULTRET, 0); 48 | 49 | lua_close(pState); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /reg_test.lua: -------------------------------------------------------------------------------- 1 | print(test0()) 2 | print(test1(10)) 3 | print(test2(12, 1)) 4 | print(test3("Hello World")) 5 | print(test4()) -------------------------------------------------------------------------------- /reghelper.h: -------------------------------------------------------------------------------- 1 | #ifndef register_h 2 | #define register_h 3 | 4 | #include 5 | 6 | extern "C" 7 | { 8 | #include "lua.h" 9 | #include "lauxlib.h" 10 | #include "lualib.h" 11 | } 12 | 13 | template 14 | struct TypeHelper{}; 15 | 16 | void getValue(TypeHelper, lua_State* pState, int index) 17 | { 18 | 19 | } 20 | 21 | bool getValue(TypeHelper, lua_State* pState, int index) 22 | { 23 | return lua_toboolean(pState, index) == 1; 24 | } 25 | 26 | char getValue(TypeHelper, lua_State* pState, int index) 27 | { 28 | return static_cast(lua_tonumber(pState, index)); 29 | } 30 | 31 | short getValue(TypeHelper, lua_State* pState, int index) 32 | { 33 | return static_cast(lua_tonumber(pState, index)); 34 | } 35 | 36 | int getValue(TypeHelper, lua_State* pState, int index) 37 | { 38 | return static_cast(lua_tonumber(pState, index)); 39 | } 40 | 41 | long getValue(TypeHelper, lua_State* pState, int index) 42 | { 43 | return static_cast(lua_tonumber(pState, index)); 44 | } 45 | 46 | unsigned char getValue(TypeHelper, lua_State* pState, int index) 47 | { 48 | return static_cast(lua_tonumber(pState, index)); 49 | } 50 | 51 | unsigned short getValue(TypeHelper, lua_State* pState, int index) 52 | { 53 | return static_cast(lua_tonumber(pState, index)); 54 | } 55 | 56 | unsigned int getValue(TypeHelper, lua_State* pState, int index) 57 | { 58 | return static_cast(lua_tonumber(pState, index)); 59 | } 60 | 61 | unsigned long getValue(TypeHelper, lua_State* pState, int index) 62 | { 63 | return static_cast(lua_tonumber(pState, index)); 64 | } 65 | 66 | char* getValue(TypeHelper, lua_State* pState, int index) 67 | { 68 | return const_cast(lua_tostring(pState, index)); 69 | } 70 | 71 | const char* getValue(TypeHelper, lua_State* pState, int index) 72 | { 73 | return lua_tostring(pState, index); 74 | } 75 | 76 | float getValue(TypeHelper, lua_State* pState, int index) 77 | { 78 | return static_cast(lua_tonumber(pState, index)); 79 | } 80 | 81 | double getValue(TypeHelper, lua_State* pState, int index) 82 | { 83 | return static_cast(lua_tonumber(pState, index)); 84 | } 85 | 86 | void pushValue(lua_State* pState, bool value) 87 | { 88 | lua_pushboolean(pState, int(value)); 89 | } 90 | 91 | void pushValue(lua_State* pState, char value) 92 | { 93 | lua_pushnumber(pState, value); 94 | } 95 | 96 | void pushValue(lua_State* pState, short value) 97 | { 98 | lua_pushnumber(pState, value); 99 | } 100 | 101 | void pushValue(lua_State* pState, int value) 102 | { 103 | lua_pushnumber(pState, value); 104 | } 105 | 106 | void pushValue(lua_State* pState, long value) 107 | { 108 | lua_pushnumber(pState, value); 109 | } 110 | 111 | void pushValue(lua_State* pState, unsigned char value) 112 | { 113 | lua_pushnumber(pState, value); 114 | } 115 | 116 | void pushValue(lua_State* pState, unsigned short value) 117 | { 118 | lua_pushnumber(pState, value); 119 | } 120 | 121 | void pushValue(lua_State* pState, unsigned int value) 122 | { 123 | lua_pushnumber(pState, value); 124 | } 125 | 126 | void pushValue(lua_State* pState, unsigned long value) 127 | { 128 | lua_pushnumber(pState, value); 129 | } 130 | 131 | void pushValue(lua_State* pState, char* value) 132 | { 133 | lua_pushstring(pState, value); 134 | } 135 | 136 | void pushValue(lua_State* pState, const char* value) 137 | { 138 | lua_pushstring(pState, value); 139 | } 140 | 141 | void pushValue(lua_State* pState, float value) 142 | { 143 | lua_pushnumber(pState, value); 144 | } 145 | 146 | void pushValue(lua_State* pState, double value) 147 | { 148 | lua_pushnumber(pState, value); 149 | } 150 | 151 | template 152 | class CCallHelper 153 | { 154 | public: 155 | static int call(Ret (*func)(), lua_State* pState) 156 | { 157 | Ret ret = (*func)(); 158 | pushValue(pState, ret); 159 | return 1; 160 | } 161 | 162 | template 163 | static int call(Ret (*func)(P1), lua_State* pState) 164 | { 165 | P1 p1 = getValue(TypeHelper(), pState, 1); 166 | Ret ret = (*func)(p1); 167 | pushValue(pState, ret); 168 | return 1; 169 | } 170 | 171 | template 172 | static int call(Ret (*func)(P1, P2), lua_State* pState) 173 | { 174 | P1 p1 = getValue(TypeHelper(), pState, 1); 175 | P2 p2 = getValue(TypeHelper(), pState, 2); 176 | Ret ret = (*func)(p1, p2); 177 | pushValue(pState, ret); 178 | return 1; 179 | } 180 | 181 | template 182 | static int call(Ret (*func)(P1, P2, P3), lua_State* pState) 183 | { 184 | P1 p1 = getValue(TypeHelper(), pState, 1); 185 | P2 p2 = getValue(TypeHelper(), pState, 2); 186 | P3 p3 = getValue(TypeHelper(), pState, 3); 187 | Ret ret = (*func)(p1, p2, p3); 188 | pushValue(pState, ret); 189 | return 1; 190 | } 191 | }; 192 | 193 | template<> 194 | class CCallHelper 195 | { 196 | public: 197 | static int call(void (*func)(), lua_State* pState) 198 | { 199 | (*func)(); 200 | return 0; 201 | } 202 | 203 | template 204 | static int call(void (*func)(P1), lua_State* pState) 205 | { 206 | P1 p1 = getValue(TypeHelper(), pState, 1); 207 | (*func)(p1); 208 | return 0; 209 | } 210 | 211 | template 212 | static int call(void (*func)(P1, P2), lua_State* pState) 213 | { 214 | P1 p1 = getValue(TypeHelper(), pState, 1); 215 | P2 p2 = getValue(TypeHelper(), pState, 2); 216 | (*func)(p1, p2); 217 | return 0; 218 | } 219 | 220 | template 221 | static int call(void (*func)(P1, P2, P3), lua_State* pState) 222 | { 223 | P1 p1 = getValue(TypeHelper(), pState, 1); 224 | P2 p2 = getValue(TypeHelper(), pState, 2); 225 | P3 p3 = getValue(TypeHelper(), pState, 3); 226 | (*func)(p1, p2, p3); 227 | return 0; 228 | } 229 | }; 230 | 231 | template 232 | class CCallDispatcher 233 | { 234 | public: 235 | template 236 | static int dispatch(Ret (*func)(), lua_State* pState) 237 | { 238 | return CCallHelper::call(func, pState); 239 | } 240 | 241 | template 242 | static int dispatch(Ret (*func)(P1), lua_State* pState) 243 | { 244 | return CCallHelper::call(func, pState); 245 | } 246 | 247 | template 248 | static int dispatch(Ret (*func)(P1, P2), lua_State* pState) 249 | { 250 | return CCallHelper::call(func, pState); 251 | } 252 | 253 | template 254 | static int dispatch(Ret (*func)(P1, P2, P3), lua_State* pState) 255 | { 256 | return CCallHelper::call(func, pState); 257 | } 258 | }; 259 | 260 | void* getRegFunction(lua_State* pState) 261 | { 262 | return lua_touserdata(pState, lua_upvalueindex(1)); 263 | } 264 | 265 | template 266 | class CCallRegister 267 | { 268 | public: 269 | static int call(lua_State* pState) 270 | { 271 | Func* func = static_cast(getRegFunction(pState)); 272 | return CCallDispatcher::dispatch(*func, pState); 273 | } 274 | }; 275 | 276 | template 277 | void regFunction(lua_State* pState, Func func, const char* funcName) 278 | { 279 | int funcSize = sizeof(Func); 280 | void* data = lua_newuserdata(pState, funcSize); 281 | memcpy(data, &func, funcSize); 282 | 283 | lua_pushcclosure(pState, CCallRegister::call, 1); 284 | lua_setglobal(pState, funcName); 285 | } 286 | 287 | #define REGISTER_FUNCTION(state, func) regFunction(state, func, #func) 288 | 289 | #endif --------------------------------------------------------------------------------