我有以下結構(歡迎對架構進行更一般的批評):
- 我有一個相當大的 C 程式在做無數的事情。
- 為了提供腳本,大量低級命令由 Lua 處理。
- 每個“命令”都有一個關聯的 Lua 片段,當必須執行“命令”時呼叫該片段。
- Lua 片段可能會回呼(非常低級的)C 函式,但我沒關系。
- 一旦啟動“命令”,Lua 片段就會退出。
- “命令”實際上是在 Lua 和 C 之外執行的(想想像開始視頻播放或錄制之類的東西:命令可能是“開始”、“停止”、“倒帶”……但它實際上并不是從程式中執行的)。
- 為了知道“命令”是否終止并最終獲得退出狀態,我需要主動輪詢命令(我沒有回呼、加入或類似功能)。
現在真正的問題:
在某些情況下,Lua 片段知道我應該安排特定 Lua 函式的一些定時呼叫;這可能是一次性的(處理超時)或回圈的(處理輪詢)。
我可以輕松地提供一個 C 函式來啟動一個執行緒來處理需求,但我不知道如何向 C 提供有關必須呼叫哪個 Lua 函式以及如何使用它的資訊。
我當前的 Lua 類(還沒有定時回呼)看起來像:
static inline bool is_whitespace(const std::string& s) {
return std::all_of(s.begin(), s.end(), isspace);
}
class Lua {
lua_State *state;
std::map<std::string, int> fragments;
void push(std::string const& str) { lua_pushstring(state, str.c_str()); }
void push(char const* str) { lua_pushstring(state, str); }
void push(bool value) { lua_pushboolean(state, value); }
void push(uint32_t value) { lua_pushinteger(state, value); }
void push(int value) { lua_pushinteger(state, value); }
void push(double value) { lua_pushnumber(state, value); }
public:
void push(std::nullptr_t) = delete;
Lua() : state(luaL_newstate()) {
luaL_openlibs(state);
}
void register_c_func(const char *name, lua_CFunction func) {
lua_register(state, name, func);
}
bool is_snippet(const std::string &name) {
return fragments.count(name);
}
int register_snippet(const char *name, const char *fragment) {
if (is_snippet(name)) {
SPDLOG_ERROR("lua::register_snippet({}): ERROR name already present", name);
return LUA_NOREF;
}
if (!is_whitespace(fragment)) {
auto ret = luaL_loadstring(state, fragment);
if (ret != LUA_OK) {
SPDLOG_ERROR("lua::register_snippet({}): Lua registration failed ({})", name, ret);
} else {
auto r = luaL_ref(state, LUA_REGISTRYINDEX);
SPDLOG_TRACE("lua::register_snippet({}, {}): {}", name, fragment, r);
fragments[name] = r;
return r;
}
} else {
SPDLOG_WARN("lua::register_snippet({}): has empty Lua fragment", name);
}
return LUA_NOREF;
}
template<typename... Args> bool exec(const std::string &name, Args... args){
if (is_snippet(name)) {
lua_rawgeti(state, LUA_REGISTRYINDEX, fragments.at(name));
((push(std::forward<Args>(args))), ...);
int nargs = sizeof ...(Args);
SPDLOG_TRACE("lua::exec({}, {}): {}", name, fragments.at(name), nargs);
lua_pcall(state, nargs, LUA_MULTRET, 0);
return true;
} else {
SPDLOG_WARN("lua::exec({}): has no Lua fragment", name);
return false;
}
}
void exec(const char* fragment) {
SPDLOG_TRACE("lua::exec(): '{}'", fragment);
auto ret = luaL_dostring(state, fragment);
if (ret)
SPDLOG_ERROR("lua::exec(): ERROR {}", ret);
}
};
extern Lua master_lua;
Lua 初始化、C 函式注冊和片段注冊不在此范圍內。
uj5u.com熱心網友回復:
C 函式只需要采用以下形式。
static int registerCallback(lua_State* L)
{
const char* callbackName = luaL_checkstring(L, 1);
//make a copy if you want to save it out of the scope
return 0;
}
lua_register(L, "registerCallback", registerCallback);
然后在 lua 中,您可以將名稱傳遞給它。
registerCallback("my_callback_function_name")
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/515308.html
標籤:C lua
下一篇:如何將鄰接矩陣轉換為關聯矩陣
