#include #include #include #include #include #include #include namespace fs = std::filesystem; std::string to_full(const std::string& path) { fs::path base; if (fs::path(path).is_relative()) { base = fs::current_path(); base.append(path); } else { base = fs::path(path); } fs::path ret = fs::absolute(base); return ret.string(); } struct LuaFunction { std::string name; std::string brief; std::vector> params; // (name, type, description) std::string returnType; }; // 解析 C++ 代码并提取函数信息 std::vector parse_cpp(const std::string& cpp_code) { std::vector functions; std::regex func_regex(R"(///\s*@brief\s*(.*))"); std::regex param_regex(R"(///\s*@param\s*(\w+)\s*(\w+)\s*(.*))"); std::regex return_regex(R"(///\s*@return\s*(.*))"); std::regex name_regex(R"(\bint\s+(\w+)\s*\()"); LuaFunction current; bool inFunction = false; std::istringstream stream(cpp_code); std::string line; while (std::getline(stream, line)) { std::smatch match; if (std::regex_search(line, match, func_regex)) { current.brief = match[1].str(); inFunction = true; } else if (std::regex_search(line, match, param_regex)) { // 将参数的name, type和description存储到params中 current.params.emplace_back(match[1].str(), match[2].str(), match[3].str()); } else if (std::regex_search(line, match, return_regex)) { current.returnType = match[1].str().empty() ? "boolean" : match[1].str(); } else if (std::regex_search(line, match, name_regex)) { current.name = match[1].str(); } else if (inFunction && line.find("}") != std::string::npos) { functions.push_back(current); current = LuaFunction(); inFunction = false; } } return functions; } // 生成 Lua 绑定文件 void generate_lua_file(const std::vector& functions, const std::string& filename, const std::string& mod_name) { std::ofstream out(filename); if (!out) { std::cerr << "can't create file: " << filename << std::endl; return; } std::string mod_call = mod_name + "_call"; std::string mod_call_p = mod_name + "_call."; out << "---@meta\n"; out << "local " << mod_call << " = require(\"" << mod_name << "\")\n\n"; out << "local M = {}\n\n"; for (const auto& func : functions) { out << "--- " << func.brief << "\n"; for (const auto& param : func.params) { out << "--- @param " << std::get<0>(param) << " " << std::get<1>(param) << " " << std::get<2>(param) << "\n"; } out << "--- @return " << func.returnType << "\n"; out << "function M." << func.name << "("; for (size_t i = 0; i < func.params.size(); ++i) { out << std::get<0>(func.params[i]); if (i < func.params.size() - 1) out << ", "; } out << ")\n return " << mod_call_p << func.name << "("; for (size_t i = 0; i < func.params.size(); ++i) { out << std::get<0>(func.params[i]); if (i < func.params.size() - 1) out << ", "; } out << ")\nend\n\n"; } out << "return M\n"; out.close(); std::cout << "Lua file gen success: " << filename << std::endl; } // 主函数 int main(int argc, char* argv[]) { if (argc < 4) { std::cout << "arg1: cxx file.\n"; std::cout << "arg2: module name.\n"; std::cout << "arg3: out dir.\n"; return -1; } std::string arg_file(argv[1]); std::string arg_mod(argv[2]); std::string arg_out(argv[3]); arg_file = to_full(arg_file); arg_out = to_full(arg_out); std::string out_file = fs::path(arg_out).append(arg_mod + ".lua").string(); std::cout << "file: " << arg_file << std::endl; std::cout << "mod: " << arg_mod << std::endl; std::cout << "out: " << arg_out << std::endl; if (!fs::exists(arg_file)) { std::cerr << "file not found: " << arg_file << std::endl; return -2; } try { if (!fs::exists(arg_out)) { fs::create_directories(arg_out); } } catch (const std::exception& e) { std::cerr << "create dir auto failed: " << e.what() << '\n'; return -3; } std::string s; std::ifstream in(arg_file); if (!in.is_open()) { std::cerr << "open file failed: " << arg_file << std::endl; return -1; } std::istreambuf_iterator iterf(in); std::istreambuf_iterator iter; std::string content(iterf, iter); std::vector functions = parse_cpp(content); generate_lua_file(functions, out_file, arg_mod); return 0; }