├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── README.md ├── cmakeconf ├── building_output.cmake └── compiler_conf.cmake ├── md └── lua_package_load.md └── samples ├── 0_luastate ├── CMakeLists.txt └── main.cpp ├── 1_loadscript ├── CMakeLists.txt └── main.cpp ├── 2_call_and_ret ├── CMakeLists.txt └── main.cpp ├── 3_load_to_package ├── CMakeLists.txt └── main.cpp ├── 4_reg_c_closure ├── CMakeLists.txt └── main.cpp ├── 5_lua_oop ├── CMakeLists.txt └── main.cpp └── CMakeLists.txt /.gitignore: -------------------------------------------------------------------------------- 1 | bin/Windows_* 2 | build/* 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "3rd/lua"] 2 | path = 3rd/lua 3 | url = https://github.com/lua/lua.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 3.15) 2 | 3 | project(lua_api_tutorial) 4 | 5 | set(TUTORIAL_ROOT ${CMAKE_SOURCE_DIR}) 6 | 7 | include(cmakeconf/compiler_conf.cmake) 8 | include(cmakeconf/building_output.cmake) 9 | 10 | add_subdirectory(samples) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lua_api_tutorial 2 | lua api tutorial by -久寿川 from 像素软件 3 | check branches to locate the chapter 4 | -------------------------------------------------------------------------------- /cmakeconf/building_output.cmake: -------------------------------------------------------------------------------- 1 | IF(ANDROID) 2 | SET(OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/android/${ANDROID_ABI}) 3 | ELSEIF(IOS) 4 | SET(OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/iOS/${IOS_PLATFORM}) 5 | ELSE() 6 | IF(WIN32) 7 | SET(USE_GUI ON) 8 | ENDIF() 9 | 10 | SET(OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${CMAKE_SYSTEM_NAME}_${ARCH_BITS}) 11 | ENDIF() 12 | 13 | MESSAGE("SYSTEM NAME: " ${CMAKE_SYSTEM_NAME}) 14 | MESSAGE("OUTPUT DIRECTORY: " ${OUTPUT_DIRECTORY}) 15 | 16 | SET(OUTPUT_DIRECTORY_DEBUG ${OUTPUT_DIRECTORY}_Debug) 17 | SET(OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY}_Release) 18 | 19 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}) 20 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}) 21 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}) 22 | 23 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${OUTPUT_DIRECTORY_DEBUG}) 24 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${OUTPUT_DIRECTORY_DEBUG}) 25 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${OUTPUT_DIRECTORY_DEBUG}) 26 | 27 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY_RELEASE}) 28 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY_RELEASE}) 29 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY_RELEASE}) -------------------------------------------------------------------------------- /cmakeconf/compiler_conf.cmake: -------------------------------------------------------------------------------- 1 | IF(CMAKE_SIZEOF_VOID_P EQUAL 8) 2 | SET(ARCH_BITS 64) 3 | ELSE() 4 | SET(ARCH_BITS 32) 5 | ENDIF() 6 | 7 | if( ANDROID ) 8 | # android platform 9 | set( TARGET_ARCH ${CMAKE_ANDROID_ARCH_ABI} ) 10 | if( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" ) 11 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fdeclspec -g -Wall -pthread") 12 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fdeclspec -pthread") 13 | add_link_options("-Wl,--build-id=sha1") 14 | set(TARGET_ARCH ${CMAKE_ANDROID_ARCH_ABI} ) 15 | else() 16 | message("why not clang!?!?") 17 | endif() 18 | # add basic NDK native library 19 | find_library( log log ) 20 | find_library( android android ) 21 | elseif( CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") 22 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -g -Wall -pthread") 23 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -pthread") 24 | elseif( APPLE ) 25 | if( IOS ) 26 | set( TARGET_ARCH iOS ) # iOS platform 27 | else() 28 | set( TARGET_ARCH macOS ) # macOS platform 29 | endif() 30 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++14 -g -Wall") 31 | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -std=c99 -g") 32 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++14 -O2 -Wunused-function") 33 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -std=c99 -O2 -pthread") 34 | elseif( WIN32 ) 35 | # windows platform 36 | if( DEFINED TARGET_ARCH ) 37 | if( ${TARGET_ARCH} STREQUAL x86 ) 38 | elseif( ${TARGET_ARCH} STREQUAL x64 ) 39 | else() 40 | set( TARGET_ARCH x64 ) 41 | message("Invalid Win32 Architechture, set architecture to 'x64'...") 42 | endif() 43 | else() 44 | set( TARGET_ARCH x64 ) 45 | message("Architechture was not set, set architecture to 'x64'...") 46 | endif() 47 | # MingW Compilers 48 | # if( MINGW ) 49 | # message("compiler: mingw") 50 | # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++14 -g -Wall -pthread") 51 | # set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -std=c99 -g -pthread") 52 | # set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++14 -O2 -pthread -Wunused-function") 53 | # set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2 -pthread") 54 | # # 55 | # if( GX_BITS STREQUAL 64 ) 56 | # set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -m64") 57 | # set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -m64") 58 | # elseif(GX_BITS STREQUAL 32) 59 | # set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") 60 | # endif() 61 | # endif() 62 | # Microsoft Visual C++ Compilers 63 | if(MSVC) 64 | message("compiler: msvc") 65 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++14 /bigobj") 66 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /std:c++14 /bigobj") 67 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /std:c++14 /bigobj /fp:fast /Gy /Oi /Oy /O2 /Ot /Zi /EHsc ") 68 | ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) 69 | IF(CMAKE_CL_64) 70 | set( TARGET_ARCH "x64" ) 71 | ELSE(CMAKE_CL_64) 72 | set( TARGET_ARCH "x86" ) 73 | ENDIF(CMAKE_CL_64) 74 | endif() 75 | if( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" ) 76 | message("compiler: clang") 77 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++14 -g -Wall") 78 | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -std=c99 -g") 79 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++14 -O2 -Wunused-function") 80 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2") 81 | set(TARGET_ARCH ${CMAKE_ANDROID_ARCH_ABI} ) 82 | endif() 83 | endif() 84 | 85 | message( "target platform : ${CMAKE_SYSTEM_NAME}") 86 | 87 | set( SOLUTION_DIR ${CMAKE_CURRENT_SOURCE_DIR} ) -------------------------------------------------------------------------------- /md/lua_package_load.md: -------------------------------------------------------------------------------- 1 | # Lua package loading 2 | 3 | 1. 生成chunk push到栈顶 4 | 2. 创建table,设置给_G表 _G["pkg"] = {} 5 | 3. 给这个table设置元表,元表继承_G表的访问域(__index) 6 | 4. 设置upvalue 7 | 5. 执行code chunk -------------------------------------------------------------------------------- /samples/0_luastate/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(lua_state) 2 | 3 | target_sources(lua_state 4 | PRIVATE 5 | ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp 6 | ) 7 | 8 | target_link_libraries(lua_state 9 | PRIVATE 10 | lua 11 | ) -------------------------------------------------------------------------------- /samples/0_luastate/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | extern "C" { 3 | #include 4 | #include 5 | #include 6 | } 7 | 8 | int main() { 9 | lua_State* state = luaL_newstate(); 10 | luaL_openlibs(state); { 11 | // some code 12 | } 13 | lua_close(state); 14 | return 0; 15 | } -------------------------------------------------------------------------------- /samples/1_loadscript/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(load_script) 2 | 3 | target_sources(load_script 4 | PRIVATE 5 | ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp 6 | ) 7 | 8 | target_link_libraries(load_script 9 | PRIVATE 10 | lua 11 | ) -------------------------------------------------------------------------------- /samples/1_loadscript/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | extern "C" { 4 | #include 5 | #include 6 | #include 7 | } 8 | 9 | char const* script = R"( 10 | function helloworld() 11 | print('hello,world!') 12 | end 13 | helloworld() 14 | )"; 15 | 16 | int main() { 17 | lua_State* state = luaL_newstate(); 18 | luaL_openlibs(state); { 19 | auto rst = luaL_loadbuffer( state, script, strlen(script), "helloworld"); 20 | if(rst != 0) { 21 | if(lua_isstring(state, -1)) { 22 | auto msg = lua_tostring(state, -1); 23 | printf("load script failed : %s\n", msg); 24 | lua_pop(state, 1); 25 | } 26 | return -1; 27 | } 28 | if(lua_pcall(state, 0, 0, 0)) { 29 | if(lua_isstring(state, -1)) { 30 | auto msg = lua_tostring(state, -1); 31 | printf("call function chunk failed : %s\n", msg); 32 | lua_pop(state, 1); 33 | } 34 | } 35 | } 36 | lua_close(state); 37 | return 0; 38 | } -------------------------------------------------------------------------------- /samples/2_call_and_ret/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(call_and_ret) 2 | 3 | target_sources(call_and_ret 4 | PRIVATE 5 | ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp 6 | ) 7 | 8 | target_link_libraries(call_and_ret 9 | PRIVATE 10 | lua 11 | ) -------------------------------------------------------------------------------- /samples/2_call_and_ret/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | extern "C" { 4 | #include 5 | #include 6 | #include 7 | } 8 | 9 | char const* script = R"( 10 | function helloworld() 11 | print('hello,world!') 12 | end 13 | function my_pow(x,y) 14 | return x^y 15 | end 16 | )"; 17 | 18 | int main() { 19 | lua_State* state = luaL_newstate(); 20 | luaL_openlibs(state); 21 | { 22 | auto rst = luaL_loadbuffer( state, script, strlen(script), "helloworld"); 23 | if(rst != 0) { 24 | if(lua_isstring(state, -1)) { 25 | auto msg = lua_tostring(state, -1); 26 | printf("load script failed : %s\n", msg); 27 | lua_pop(state, 1); 28 | } 29 | return -1; 30 | } 31 | if(lua_pcall(state, 0, 0, 0)) { 32 | if(lua_isstring(state, -1)) { 33 | auto msg = lua_tostring(state, -1); 34 | printf("call function chunk failed : %s\n", msg); 35 | lua_pop(state, 1); 36 | } 37 | } 38 | // call my_pow 39 | rst = lua_getglobal(state, "my_pow"); 40 | if(!lua_isfunction(state, -1)) { 41 | printf("function named 'my_pow' not found!\n"); 42 | return -1; 43 | } 44 | lua_pushnumber(state, 2); 45 | lua_pushnumber(state, 8); 46 | 47 | rst = lua_pcall(state, 2, 1, 0); 48 | if(rst != 0) { 49 | if(lua_isstring(state, -1)) { 50 | auto msg = lua_tostring(state, -1); 51 | printf("call function chunk failed : %s\n", msg); 52 | lua_pop(state, 1); 53 | } 54 | } 55 | if(lua_isnumber(state, -1)) { 56 | lua_Number val = lua_tonumber(state, -1); 57 | printf("my_pow ret : %f", (float)val); 58 | } 59 | } 60 | lua_close(state); 61 | return 0; 62 | } -------------------------------------------------------------------------------- /samples/3_load_to_package/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(load_to_package) 2 | 3 | target_sources(load_to_package 4 | PRIVATE 5 | ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp 6 | ) 7 | 8 | target_link_libraries(load_to_package 9 | PRIVATE 10 | lua 11 | ) -------------------------------------------------------------------------------- /samples/3_load_to_package/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | extern "C" { 5 | #include 6 | #include 7 | #include 8 | } 9 | 10 | char const* script = R"( 11 | function helloworld() 12 | print('hello,world!') 13 | end 14 | function my_pow(x,y) 15 | return x^y 16 | end 17 | )"; 18 | 19 | char const* script_1 = R"( 20 | pkg.helloworld() 21 | )"; 22 | /* 23 | _G = { 24 | "helloworld" = function print("hello,world") 25 | } 26 | _G = { 27 | "pgk" = { 28 | metatable = { 29 | "__index" = _G 30 | } 31 | "helloworld" = function print("hello,world") 32 | } 33 | } 34 | ```lua 35 | pkg.helloworld() 36 | ``` 37 | */ 38 | int main() { 39 | lua_State* state = luaL_newstate(); 40 | luaL_openlibs(state); 41 | { 42 | auto rst = luaL_loadbuffer( state, script, strlen(script), "helloworld"); 43 | if(rst != 0) { 44 | if(lua_isstring(state, -1)) { 45 | auto msg = lua_tostring(state, -1); 46 | printf("load script failed : %s\n", msg); 47 | lua_pop(state, 1); 48 | } 49 | return -1; 50 | } 51 | // call the code chunk 52 | lua_getglobal(state, "_G"); 53 | if(lua_istable(state, -1)) { // chunk; _G 54 | lua_newtable(state); // chunk;_G ; new_table 55 | lua_pushstring(state, "pkg"); //chunk;_G; new_table; "pkg"; 56 | lua_pushvalue(state, -2); //chunk; _G; new_table; "pkg"; new_table 57 | lua_rawset(state, -4); // chunk;_G; new_table; 58 | char const* upvalueName = lua_setupvalue(state, -3, 1); // chunk; _G 59 | assert(strcmp(upvalueName, "_ENV") == 0 && "upvalue name must be '_ENV'"); 60 | lua_newtable(state); // chunk; _G; metatable 61 | lua_pushstring(state, "__index"); // chunk; _G; metatable; "__index"; 62 | lua_pushvalue(state, -3); // chunk; _G; metatable; "__index"; _G 63 | lua_rawset(state, -3); // chunk; _G; metatable 64 | lua_pushstring(state, "pkg"); // chunk; _G; metatable; "pkg"(string) 65 | lua_rawget(state, -3); // chunk; _G; metatable; "pkg"(table) 66 | lua_pushvalue(state, -2); // chunk; _G; metatable; "pkg"(table); metatable; 67 | lua_setmetatable(state, -2); // chunk; _G; metatable;"pkg"(table); 68 | lua_pop(state, 3); // chunk 69 | // lua_pop(state, 1); 70 | } // chunk 71 | // 执行chunk 72 | if(lua_pcall(state, 0, 0, 0)) { 73 | if(lua_isstring(state, -1)) { 74 | auto msg = lua_tostring(state, -1); 75 | printf("call function chunk failed : %s\n", msg); 76 | lua_pop(state, 1); 77 | } 78 | } 79 | // 加载 script_1 80 | rst = luaL_loadbuffer( state, script_1, strlen(script_1), "script_1"); 81 | if(rst != 0) { 82 | if(lua_isstring(state, -1)) { 83 | auto msg = lua_tostring(state, -1); 84 | printf("load script failed : %s\n", msg); 85 | lua_pop(state, 1); 86 | } 87 | return -1; 88 | } 89 | if(lua_pcall(state, 0, 0, 0)) { 90 | if(lua_isstring(state, -1)) { 91 | auto msg = lua_tostring(state, -1); 92 | printf("call function chunk failed : %s\n", msg); 93 | lua_pop(state, 1); 94 | } 95 | } 96 | } 97 | lua_close(state); 98 | return 0; 99 | } -------------------------------------------------------------------------------- /samples/4_reg_c_closure/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(reg_c_closure) 2 | 3 | target_sources(reg_c_closure 4 | PRIVATE 5 | ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp 6 | ) 7 | 8 | target_link_libraries(reg_c_closure 9 | PRIVATE 10 | lua 11 | ) -------------------------------------------------------------------------------- /samples/4_reg_c_closure/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | extern "C" { 7 | #include 8 | #include 9 | #include 10 | } 11 | 12 | char const* script = R"( 13 | local val = pow_from_c(2,5) 14 | print(""..val) 15 | )"; 16 | 17 | int __cdecl pow_from_c(lua_State* state) { 18 | int param_count = lua_gettop(state); 19 | if(param_count != 2) { 20 | return 0; 21 | } 22 | if(lua_isinteger(state, 1) && lua_isinteger(state, 2)) { 23 | auto x = lua_tointeger(state, 1); 24 | auto y = lua_tointeger(state, 2); 25 | int rst = (int)pow(x, y); 26 | lua_pushinteger(state, rst); 27 | return 1; 28 | } 29 | return 0; 30 | } 31 | 32 | /** 33 | * 34 | * _G = { 35 | * "pow_from_c" = pow_from_c; 36 | * } 37 | * */ 38 | 39 | int main() { 40 | lua_State* state = luaL_newstate(); 41 | luaL_openlibs(state); 42 | { 43 | lua_getglobal(state, "_G"); 44 | lua_pushstring(state, "pow_from_c"); 45 | lua_pushcclosure(state, pow_from_c, 0); // _G; "pow_from_c"; closure 46 | lua_rawset(state, -3); // _G 47 | lua_pop(state, 1); 48 | // 49 | auto rst = luaL_loadbuffer( state, script, strlen(script), "reg_c_closure"); 50 | if(rst != 0) { 51 | if(lua_isstring(state, -1)) { 52 | auto msg = lua_tostring(state, -1); 53 | printf("load script failed : %s\n", msg); 54 | lua_pop(state, 1); 55 | } 56 | return -1; 57 | } 58 | // 执行chunk 59 | if(lua_pcall(state, 0, 0, 0)) { 60 | if(lua_isstring(state, -1)) { 61 | auto msg = lua_tostring(state, -1); 62 | printf("call function chunk failed : %s\n", msg); 63 | lua_pop(state, 1); 64 | } 65 | } 66 | } 67 | lua_close(state); 68 | return 0; 69 | } -------------------------------------------------------------------------------- /samples/5_lua_oop/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(lua_oop) 2 | 3 | target_sources(lua_oop 4 | PRIVATE 5 | ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp 6 | ) 7 | 8 | target_link_libraries(lua_oop 9 | PRIVATE 10 | lua 11 | ) -------------------------------------------------------------------------------- /samples/5_lua_oop/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | extern "C" { 7 | #include 8 | #include 9 | #include 10 | } 11 | 12 | char const* script = R"( 13 | local obj_1 = create_game_object(1); 14 | local obj_2 = create_game_object(1); 15 | local obj_3 = create_game_object(2); 16 | local rst1 = obj_1:equal(obj_2) 17 | local rst2 = obj_1:equal(obj_3) 18 | print(rst1,";",rst2) 19 | print(""..obj_1:id()) 20 | )"; 21 | class GameObject { 22 | private: 23 | uint32_t _id; 24 | public: 25 | static size_t registry_value; 26 | public: 27 | GameObject(uint32_t id) 28 | : _id(id) 29 | {} 30 | uint32_t id() const { 31 | return _id; 32 | } 33 | bool equal( GameObject* obj ) { 34 | return _id == obj->_id; 35 | } 36 | }; 37 | 38 | size_t GameObject::registry_value = 0; 39 | /** 40 | * userdata : { 41 | * metatable : { 42 | * __index = { 43 | * equal = function() {}, 44 | * id = function() {} 45 | * } 46 | * } 47 | * } 48 | * */ 49 | 50 | int GameObject_equal( lua_State* state ) { 51 | int arg_count = lua_gettop(state); 52 | if(arg_count != 2) { 53 | return 0; 54 | } 55 | if(lua_isuserdata(state, 1) && lua_isuserdata(state, 2)) { 56 | void* userdata_self = lua_touserdata(state, 1); 57 | void* userdata_that = lua_touserdata(state, 2); 58 | GameObject* obj1 = (GameObject*)userdata_self; 59 | GameObject* obj2 = (GameObject*)userdata_that; 60 | auto rst = obj1->equal(obj2); 61 | lua_pushboolean(state, rst); 62 | return 1; 63 | } 64 | return 0; 65 | } 66 | 67 | int GameObject_id(lua_State* state) { 68 | GameObject* this_obj = (GameObject*)lua_touserdata(state, 1); 69 | auto rst = this_obj->id(); 70 | lua_pushinteger(state, rst); 71 | return 1; 72 | } 73 | 74 | int create_game_object(lua_State* state) { 75 | auto id = lua_tointeger(state, 1); 76 | void* p = lua_newuserdata(state, sizeof(GameObject)); 77 | // placement new 78 | GameObject* obj = new(p)GameObject(id); // userdata 79 | lua_rawgetp(state, LUA_REGISTRYINDEX, &GameObject::registry_value); // userdata; metatable 80 | lua_setmetatable(state, -2); // userdata 81 | return 1; 82 | } 83 | 84 | int main() { 85 | lua_State* state = luaL_newstate(); 86 | luaL_openlibs(state); 87 | { 88 | // Regist create_object to lua 89 | lua_getglobal(state, "_G"); 90 | lua_pushstring(state, "create_game_object"); 91 | lua_pushcclosure(state, create_game_object, 0); 92 | lua_rawset(state, -3); // _G 93 | lua_pop(state, 1); 94 | // reg GameObject metatable 95 | lua_newtable(state); // metatable 96 | lua_pushstring(state, "__index"); // metatable; "__index" 97 | lua_newtable(state); // metatable, "__index", index_table 98 | lua_pushstring(state,"equal"); // metatable, "__index", index_table, "equal" 99 | lua_pushcclosure(state, GameObject_equal, 0); // metatable, "__index", index_table, "equal", GameObject_equal 100 | lua_rawset(state, -3);// metatable, "__index", index_table 101 | lua_pushstring(state,"id"); // metatable, "__index", index_table, "equal" 102 | lua_pushcclosure(state, GameObject_id, 0); // metatable, "__index", index_table, "equal", GameObject_equal 103 | lua_rawset(state, -3);// metatable, "__index", index_table 104 | // 105 | lua_rawset(state, -3); // metatable 106 | lua_rawsetp(state, LUA_REGISTRYINDEX, &GameObject::registry_value); 107 | // 108 | auto rst = luaL_loadbuffer( state, script, strlen(script), "oop"); 109 | if(rst != 0) { 110 | if(lua_isstring(state, -1)) { 111 | auto msg = lua_tostring(state, -1); 112 | printf("load script failed : %s\n", msg); 113 | lua_pop(state, 1); 114 | } 115 | return -1; 116 | } 117 | // 执行chunk 118 | if(lua_pcall(state, 0, 0, 0)) { 119 | if(lua_isstring(state, -1)) { 120 | auto msg = lua_tostring(state, -1); 121 | printf("call function chunk failed : %s\n", msg); 122 | lua_pop(state, 1); 123 | } 124 | } 125 | } 126 | lua_close(state); 127 | return 0; 128 | } -------------------------------------------------------------------------------- /samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(3rd) 2 | 3 | add_library( lua STATIC ) 4 | target_sources(lua 5 | PRIVATE 6 | ${TUTORIAL_ROOT}/3rd/lua/lapi.c 7 | ${TUTORIAL_ROOT}/3rd/lua/lauxlib.c 8 | ${TUTORIAL_ROOT}/3rd/lua/lbaselib.c 9 | ${TUTORIAL_ROOT}/3rd/lua/lcode.c 10 | ${TUTORIAL_ROOT}/3rd/lua/lcorolib.c 11 | ${TUTORIAL_ROOT}/3rd/lua/lctype.c 12 | ${TUTORIAL_ROOT}/3rd/lua/ldblib.c 13 | ${TUTORIAL_ROOT}/3rd/lua/ldebug.c 14 | ${TUTORIAL_ROOT}/3rd/lua/ldo.c 15 | ${TUTORIAL_ROOT}/3rd/lua/ldump.c 16 | ${TUTORIAL_ROOT}/3rd/lua/lfunc.c 17 | ${TUTORIAL_ROOT}/3rd/lua/lgc.c 18 | ${TUTORIAL_ROOT}/3rd/lua/linit.c 19 | ${TUTORIAL_ROOT}/3rd/lua/liolib.c 20 | ${TUTORIAL_ROOT}/3rd/lua/llex.c 21 | ${TUTORIAL_ROOT}/3rd/lua/lmathlib.c 22 | ${TUTORIAL_ROOT}/3rd/lua/lmem.c 23 | ${TUTORIAL_ROOT}/3rd/lua/loadlib.c 24 | ${TUTORIAL_ROOT}/3rd/lua/lobject.c 25 | ${TUTORIAL_ROOT}/3rd/lua/lopcodes.c 26 | ${TUTORIAL_ROOT}/3rd/lua/loslib.c 27 | ${TUTORIAL_ROOT}/3rd/lua/lparser.c 28 | ${TUTORIAL_ROOT}/3rd/lua/lstate.c 29 | ${TUTORIAL_ROOT}/3rd/lua/lstring.c 30 | ${TUTORIAL_ROOT}/3rd/lua/lstrlib.c 31 | ${TUTORIAL_ROOT}/3rd/lua/ltable.c 32 | ${TUTORIAL_ROOT}/3rd/lua/ltablib.c 33 | ${TUTORIAL_ROOT}/3rd/lua/ltablib.c 34 | ${TUTORIAL_ROOT}/3rd/lua/lua.c 35 | ${TUTORIAL_ROOT}/3rd/lua/ltm.c 36 | ${TUTORIAL_ROOT}/3rd/lua/lundump.c 37 | ${TUTORIAL_ROOT}/3rd/lua/lutf8lib.c 38 | ${TUTORIAL_ROOT}/3rd/lua/lvm.c 39 | ${TUTORIAL_ROOT}/3rd/lua/lzio.c 40 | ) 41 | 42 | target_include_directories(lua 43 | INTERFACE 44 | ${TUTORIAL_ROOT}/3rd 45 | ) 46 | 47 | project(samples) 48 | 49 | add_subdirectory(0_luastate) 50 | add_subdirectory(1_loadscript) 51 | add_subdirectory(2_call_and_ret) 52 | add_subdirectory(3_load_to_package) 53 | add_subdirectory(4_reg_c_closure) 54 | add_subdirectory(5_lua_oop) --------------------------------------------------------------------------------