# dmsolpp **Repository Path**: brinkqiang/dmsolpp ## Basic Information - **Project Name**: dmsolpp - **Description**: C++ lua sol2自动化bind实现. 该库旨在简化 C++ 库的 Lua 导入过程,通过解析头文件自动生成 Lua 的接口绑定代码。利用 sol2 的高效绑定机制,无需手动编写复杂的绑定代码,即可轻松将现有的 C++ 库导出至 Lua,显著提升开发效率。 - **Primary Language**: C++ - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2021-08-23 - **Last Updated**: 2025-04-26 ## Categories & Tags **Categories**: utils **Tags**: None ## README # dmsolpp Copyright (c) 2013-2018 brinkqiang (brink.qiang@gmail.com) [![dmsolpp](https://img.shields.io/badge/brinkqiang-dmsolpp-blue.svg?style=flat-square)](https://github.com/brinkqiang/dmsolpp) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/brinkqiang/dmsolpp/blob/master/LICENSE) [![blog](https://img.shields.io/badge/Author-Blog-7AD6FD.svg)](https://brinkqiang.github.io/) [![Open Source Love](https://badges.frapsoft.com/os/v3/open-source.png)](https://github.com/brinkqiang) [![GitHub stars](https://img.shields.io/github/stars/brinkqiang/dmsolpp.svg?label=Stars)](https://github.com/brinkqiang/dmsolpp) [![GitHub forks](https://img.shields.io/github/forks/brinkqiang/dmsolpp.svg?label=Fork)](https://github.com/brinkqiang/dmsolpp) ## Build status | [Linux][lin-link] | [Mac][mac-link] | [Windows][win-link] | | :---------------: | :----------------: | :-----------------: | | ![lin-badge] | ![mac-badge] | ![win-badge] | [lin-badge]: https://github.com/brinkqiang/dmsolpp/workflows/linux/badge.svg "linux build status" [lin-link]: https://github.com/brinkqiang/dmsolpp/actions/workflows/linux.yml "linux build status" [mac-badge]: https://github.com/brinkqiang/dmsolpp/workflows/mac/badge.svg "mac build status" [mac-link]: https://github.com/brinkqiang/dmsolpp/actions/workflows/mac.yml "mac build status" [win-badge]: https://github.com/brinkqiang/dmsolpp/workflows/win/badge.svg "win build status" [win-link]: https://github.com/brinkqiang/dmsolpp/actions/workflows/win.yml "win build status" ## Intro dmsolpp export flags // export_begin // export_end ``` #ifndef __OBJECT_H_INCLUDE__ #define __OBJECT_H_INCLUDE__ #include class CObject { public: // export_begin CObject(): m_objID(0){} virtual ~CObject(){} uint64_t GetObjID(){ return m_objID;} void SetObjID(uint64_t id){ m_objID = id;} // export_end private: uint64_t m_objID; }; #endif // __OBJECT_H_INCLUDE__ ``` command ``` dmsolpp --PKG=interface.pkg ``` output ``` interface.sol.cc interface.sol.h ``` addmodule ``` oDMLuaEngine.AddModule(require_interface); ``` ```cpp #include "gtest.h" #include #include "interface.sol.h" #include "player.h" #include "dmsolpp.h" TEST(DoSolpp, DoSolpp) { CDMLuaEngine oDMLuaEngine; std::string strScriptRootPath = DMGetRootPath(); oDMLuaEngine.SetRootPath(strScriptRootPath + PATH_DELIMITER_STR + ".." + PATH_DELIMITER_STR + "script"); // 加载自动化生成代码 模块, 如果你有多个模块,需要在这里添加多个 oDMLuaEngine.AddModule(require_interface); // 使用dmlua来load 主要是他可以自动load指定目录的所有文件. sol引擎本身没有实现这个功能. if (!oDMLuaEngine.ReloadScript()) { ASSERT_TRUE(0); return; } oDMLuaEngine.DoString(R"( function add(a , b) return a + b end )"); oDMLuaEngine.DoString(R"( function addplayer(player) print("[addplayer]: " .. player:GetName()) return 1 end )"); // 获取sol引擎 auto state = oDMLuaEngine.GetSol(); int num = state["add"](1, 2); CPlayer oPlayer(5, "zhangsan"); int ret = state["test"]["main"]["dowork"](&oPlayer); int ret2 = state["addplayer"](oPlayer); // 通过lua脚本实现的对象管理器进行对象创建 对象生命周期由lua负责 reload 之后数据丢失 auto script_result = state.safe_script(R"( local interface = require("interface") local player_mgr = require("player") local player = player_mgr.create_player() local p = player_mgr.find_player(player:GetObjID()) p:Init() p:NotChange() p.OnChange = function (self) print("OnChange in lua") end p:OnChange() print(MAX_NAME_LEN) print("[1]" .. interface.GNextID()) print("[2]" .. p.NextID()) p:SetObjID(interface.GNextID()) print("[3]" .. p:GetObjID()) p:SetHP(interface.GNextID()) print("[4]" .. p:GetHP()) print("[5]" .. interface.CPlayer.NextID()) player_mgr.release_player(p) print("in sol2.lua player_mgr.create_player"); )", sol::script_throw_on_error); ASSERT_TRUE(script_result.valid()); // 通过导入的C++对象管理器进行对象创建 对象生命周期由C++负责 reload 之后数据还在 auto script_result2 = state.safe_script(R"( local interface = require("interface") local player = interface.create_player(); local p = interface.find_player(player:GetObjID()); p:Init() p:NotChange() p.OnChange = function (self) print("OnChange in lua") end p:OnChange() interface.release_player(player:GetObjID()) print("in sol2.cpp player_mgr.create_player"); )", sol::script_throw_on_error); ASSERT_TRUE(script_result2.valid()); } ``` interface.sol.cc ```cpp /******************************************************************** ** This cc file is generated by program, ** ** Please do not change it directly. ** ** Auther: brinkqiang ** ********************************************************************/ // source: interface.pkg #include "interface.sol.h" #include #include "object.h" #include "creature.h" #include "player.h" #include "playermgr.h" #include "common/types.h" #include "common/enum.h" #include "common/macros.h" #include "common/struct.h" #include "common/template.h" #include "sol/sol.hpp" namespace lua_module_interface { static sol::table require_api(sol::this_state L) { sol::state_view lua(L); sol::table module = lua.create_table(); module.new_usertype( "CObject" , sol::constructors() , sol::meta_function::garbage_collect, sol::destructor([](CObject& temp) { temp.~CObject(); }) , sol::base_classes, sol::bases<>() , "GetObjID", sol::make_reference(lua.lua_state(), &CObject::GetObjID) , "SetObjID", sol::make_reference(lua.lua_state(), &CObject::SetObjID) ); module.new_usertype( "CCreature" , sol::constructors() , sol::meta_function::garbage_collect, sol::destructor([](CCreature& temp) { temp.~CCreature(); }) , sol::base_classes, sol::bases() , "SetHP", sol::make_reference(lua.lua_state(), &CCreature::SetHP) , "SetMP", sol::make_reference(lua.lua_state(), &CCreature::SetMP) , "GetHP", sol::make_reference(lua.lua_state(), &CCreature::GetHP) , "GetMP", sol::make_reference(lua.lua_state(), &CCreature::GetMP) ); module.set_function("GNextID",&GNextID); module.new_usertype( "CPlayer" , sol::constructors() , sol::meta_function::garbage_collect, sol::destructor([](CPlayer& temp) { temp.~CPlayer(); }) , sol::base_classes, sol::bases() , "DoAction", sol::make_reference(lua.lua_state(), &CPlayer::DoAction) , "Init", sol::make_reference(lua.lua_state(), &CPlayer::Init) , "OnChange", sol::make_reference(lua.lua_state(), &CPlayer::OnChange) , "NotChange", sol::make_reference(lua.lua_state(), &CPlayer::NotChange) , "SystemChange", sol::make_reference(lua.lua_state(), &CPlayer::SystemChange) , "LoadFromDB", sol::make_reference(lua.lua_state(), &CPlayer::LoadFromDB) , "SaveDB", sol::make_reference(lua.lua_state(), &CPlayer::SaveDB) , "GetName", sol::make_reference(lua.lua_state(), &CPlayer::GetName) , "NextID", sol::make_reference(lua.lua_state(), &CPlayer::NextID) ); module.set_function("create_player",&create_player); module.set_function("find_player",&find_player); module.set_function("release_player",&release_player); module.new_usertype( "CPlayerMgr" , sol::constructors<>() , sol::base_classes, sol::bases<>() , "create_player", sol::make_reference(lua.lua_state(), &CPlayerMgr::create_player) , "find_player", sol::make_reference(lua.lua_state(), &CPlayerMgr::find_player) , "release_player", sol::make_reference(lua.lua_state(), &CPlayerMgr::release_player) ); module.new_usertype( "STaskInfo" , sol::constructors() , sol::meta_function::garbage_collect, sol::destructor([](STaskInfo& temp) { temp.~STaskInfo(); }) , sol::base_classes, sol::bases<>() , "nTaskID", &STaskInfo::nTaskID , "nTaskState", &STaskInfo::nTaskState , "nTaskCondition", &STaskInfo::nTaskCondition ); module.new_usertype( "SPos" , sol::constructors() , sol::meta_function::garbage_collect, sol::destructor([](SPos& temp) { temp.~SPos(); }) , sol::base_classes, sol::bases<>() , "x", &SPos::x , "y", &SPos::y , "z", &SPos::z ); return module; } } LUA_API int luaopen_interface(lua_State* L) { return sol::stack::call_lua(L, 1, lua_module_interface::require_api); } LUA_API int require_interface(lua_State* L) { luaL_requiref(L, "interface", luaopen_interface, 0); printf("lua module: require interface\n"); return 1; } ``` ## Contacts ## Thanks