不带括号的函数 lua c++
Function without brackets lua c++
我正在创建一个基于 Lua 脚本中调用的函数播放音乐的应用程序。我称之为音乐。问题是我需要一个不需要括号的函数。像这样:
play note("A")
这是我的完整代码:
#include <iostream>
#include <string>
extern "C"
{
#include "../lua/include/lua.h"
#include "../lua/include/lauxlib.h"
#include "../lua/include/lualib.h"
}
/*
Message codes
M8I5H: Information
MSKIE: Syntax error
M3UET: Unknown error
*/
enum class MUSICA_NOTE_ENUM
{
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
};
int musica_play(lua_State *L)
{
// Not added yet
return 1;
}
int musica_note(lua_State *L)
{
std::string note = lua_tostring(L, 1);
lua_pushnumber(L, (lua_Number)((MUSICA_NOTE_ENUM)(note.at(0) & 31)));
return 1;
}
int main(){
std::string music = R"(a = 75
play note("A")
play note("B")
play note("C")
-- play melody(melody_piono_tune)
)";
std::string m = "play note(\"A\")";
lua_State *L = luaL_newstate();
lua_register(L, "note", musica_note);
lua_register(L, "play", musica_play);
int r = luaL_dostring(L, m.c_str());
if(r == LUA_OK)
{
}else{
printf("[Line: %d, File: %s, MessageCode: MSKIE] MUSICA: There was a problem interperting the file:\n%s\n\n", __LINE__, __FILE__, lua_tostring(L, -1));
}
}
如何让播放功能无括号?
提前致谢
标准 Lua 仅支持在使用 table 构造函数或字符串文字作为其唯一参数调用函数时调用不带括号的函数。由于您希望能够使用其他值调用它,因此使这项工作起作用的唯一选择是修补 Lua 解析器。下面是你如何通过破解 Lua 的源代码来做到这一点(这个补丁是针对 Lua 5.4.1 版本准备的):
diff --git a/src/lparser.c b/src/lparser.c
index bc7d9a4..d917687 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -1795,6 +1795,44 @@ static void localstat (LexState *ls) {
}
+static void playstat (LexState *ls) {
+ FuncState *fs = ls->fs;
+ struct LHS_assign v;
+ expdesc *f = &v.v;
+ int line = ls->linenumber;
+ expdesc args;
+ int base, nparams;
+ Instruction *inst;
+
+ /* get the function ready to call like suffixedexp does */
+ singlevar(ls, f);
+ luaK_exp2nextreg(fs, f);
+
+ /* this section taken from the else inside case '(' in funcargs */
+ explist(ls, &args);
+ if (hasmultret(args.k))
+ luaK_setmultret(fs, &args);
+
+ /* this section taken from after the switch statement in funcargs */
+ lua_assert(f->k == VNONRELOC);
+ base = f->u.info; /* base register for call */
+ if (hasmultret(args.k))
+ nparams = LUA_MULTRET; /* open call */
+ else {
+ luaK_exp2nextreg(fs, &args); /* close last argument */
+ nparams = fs->freereg - (base+1);
+ }
+ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
+ luaK_fixline(fs, line);
+ fs->freereg = base+1; /* call remove function and arguments and leaves
+ (unless changed) one result */
+
+ /* this section taken from the else block in exprstat */
+ inst = &getinstruction(fs, &v.v);
+ SETARG_C(*inst, 1); /* call statement uses no results */
+}
+
+
static int funcname (LexState *ls, expdesc *v) {
/* funcname -> NAME {fieldsel} [':' NAME] */
int ismethod = 0;
@@ -1932,6 +1970,13 @@ static void statement (LexState *ls) {
gotostat(ls);
break;
}
+ case TK_NAME: {
+ if (!strcmp(getstr(ls->t.seminfo.ts), "play")) {
+ playstat(ls);
+ break;
+ }
+ }
+ /* FALLTHROUGH */
default: { /* stat -> func | assignment */
exprstat(ls);
break;
这使得 play
在语句开头时就像关键字一样。它在它之后捕获表达式,类似于 local foo, bar, baz =
的方式。我必须强调,这确实是一个 hack。你的另一个选择是用 Metalua 做同样的事情,但这限制你使用 Lua 5.1,它已经停产 8 年并且存在已知的安全问题。
我正在创建一个基于 Lua 脚本中调用的函数播放音乐的应用程序。我称之为音乐。问题是我需要一个不需要括号的函数。像这样:
play note("A")
这是我的完整代码:
#include <iostream>
#include <string>
extern "C"
{
#include "../lua/include/lua.h"
#include "../lua/include/lauxlib.h"
#include "../lua/include/lualib.h"
}
/*
Message codes
M8I5H: Information
MSKIE: Syntax error
M3UET: Unknown error
*/
enum class MUSICA_NOTE_ENUM
{
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
};
int musica_play(lua_State *L)
{
// Not added yet
return 1;
}
int musica_note(lua_State *L)
{
std::string note = lua_tostring(L, 1);
lua_pushnumber(L, (lua_Number)((MUSICA_NOTE_ENUM)(note.at(0) & 31)));
return 1;
}
int main(){
std::string music = R"(a = 75
play note("A")
play note("B")
play note("C")
-- play melody(melody_piono_tune)
)";
std::string m = "play note(\"A\")";
lua_State *L = luaL_newstate();
lua_register(L, "note", musica_note);
lua_register(L, "play", musica_play);
int r = luaL_dostring(L, m.c_str());
if(r == LUA_OK)
{
}else{
printf("[Line: %d, File: %s, MessageCode: MSKIE] MUSICA: There was a problem interperting the file:\n%s\n\n", __LINE__, __FILE__, lua_tostring(L, -1));
}
}
如何让播放功能无括号?
提前致谢
标准 Lua 仅支持在使用 table 构造函数或字符串文字作为其唯一参数调用函数时调用不带括号的函数。由于您希望能够使用其他值调用它,因此使这项工作起作用的唯一选择是修补 Lua 解析器。下面是你如何通过破解 Lua 的源代码来做到这一点(这个补丁是针对 Lua 5.4.1 版本准备的):
diff --git a/src/lparser.c b/src/lparser.c
index bc7d9a4..d917687 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -1795,6 +1795,44 @@ static void localstat (LexState *ls) {
}
+static void playstat (LexState *ls) {
+ FuncState *fs = ls->fs;
+ struct LHS_assign v;
+ expdesc *f = &v.v;
+ int line = ls->linenumber;
+ expdesc args;
+ int base, nparams;
+ Instruction *inst;
+
+ /* get the function ready to call like suffixedexp does */
+ singlevar(ls, f);
+ luaK_exp2nextreg(fs, f);
+
+ /* this section taken from the else inside case '(' in funcargs */
+ explist(ls, &args);
+ if (hasmultret(args.k))
+ luaK_setmultret(fs, &args);
+
+ /* this section taken from after the switch statement in funcargs */
+ lua_assert(f->k == VNONRELOC);
+ base = f->u.info; /* base register for call */
+ if (hasmultret(args.k))
+ nparams = LUA_MULTRET; /* open call */
+ else {
+ luaK_exp2nextreg(fs, &args); /* close last argument */
+ nparams = fs->freereg - (base+1);
+ }
+ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
+ luaK_fixline(fs, line);
+ fs->freereg = base+1; /* call remove function and arguments and leaves
+ (unless changed) one result */
+
+ /* this section taken from the else block in exprstat */
+ inst = &getinstruction(fs, &v.v);
+ SETARG_C(*inst, 1); /* call statement uses no results */
+}
+
+
static int funcname (LexState *ls, expdesc *v) {
/* funcname -> NAME {fieldsel} [':' NAME] */
int ismethod = 0;
@@ -1932,6 +1970,13 @@ static void statement (LexState *ls) {
gotostat(ls);
break;
}
+ case TK_NAME: {
+ if (!strcmp(getstr(ls->t.seminfo.ts), "play")) {
+ playstat(ls);
+ break;
+ }
+ }
+ /* FALLTHROUGH */
default: { /* stat -> func | assignment */
exprstat(ls);
break;
这使得 play
在语句开头时就像关键字一样。它在它之后捕获表达式,类似于 local foo, bar, baz =
的方式。我必须强调,这确实是一个 hack。你的另一个选择是用 Metalua 做同样的事情,但这限制你使用 Lua 5.1,它已经停产 8 年并且存在已知的安全问题。