Script lua¶
Script_lua is a basic example plugin. This wiki page is intended as a walkthrough of the code in order to help you better understand the SDK.
This plugin serves as a Lua script interpreter.
Code Walkthrough¶
The code structure for this plugin is somewhat atypical. In our header we declare a variety of functions which we define in the related cpp. However, our main class, the one from which we will build our server, is in another cpp entirely and has a utility that takes the functions that we defined and adds them to the aforementioned class.
Declarations¶
lxlua.h¶
This is a struct that defines certain objects and constants that will be used by the plugin.
typedef struct st_IntrInstance {
ILxScriptID script; // Script being executed.
ILxMonitorID monitor; // Progress monitor used by lxmon??? functions.
int askedForMonitor; // True if we asked for the monitor.
LxResult rc; // Result code from the most recently executed/queried command.
int tracing; // 1 if tracing is active, 0 if inactive.
int execFlags; // Flags provided by the caller of Run() and used for command execution.
CLxUser_LogEntry log; // For logging data
int queryAnglesAsDegrees; // True if queried angles should be returned in degrees instead of radians.
} IntrInstance;
Declaration of functions that will be used by the plugin.
1 2 3 4 5 6 7 8 9 10 11 12 | extern "C" int l_lxout(lua_State *L);
extern "C" int l_lx(lua_State *L);
extern "C" int l_lxq(lua_State *L);
extern "C" int l_lxqt(lua_State *L);
extern "C" int l_lxeval(lua_State *L);
extern "C" int l_lxok(lua_State *L);
extern "C" int l_lxres(lua_State *L);
extern "C" int l_lxtrace(lua_State *L);
extern "C" int l_lxoption(lua_State *L);
extern "C" int l_lxsetOption(lua_State *L);
extern "C" int l_lxmonInit(lua_State *L);
extern "C" int l_lxmonStep(lua_State *L);
|
lxlua.cpp¶
Here we declare a variety of scripts and services that will be used below. “extern” indicates that the objects inside have already been defined elsewhere so the compiler won’t complain.
extern "C" {
ILxScriptSysServiceID scriptSrv; /* Script system service; common to all instances */
ILxStdDialogServiceID dlgSrv; /* Standard dialog service; common to all instances */
IntrInstance intrStack[ MAX_STACK ]; /* Interpreter stack; allows scripts to execute other scripts */
int intrTop = -1; /* The current script being executed as an index into interStack */
IntrInstance *intrCur = NULL; /* The same as &intrStack[ intrTop ], or NULL if intrTop is -1 */
}
Class Declarations¶
intrlua.cpp¶
This class is intended to take a lua script and interpret it, so we need it to be a modified text editor. To this end, we inherit from Scripts_(lx-scripts.hpp)#Text_Script_Interpreter.
The first two functions of note inside the class are those with the tsi prefix, indicating that they are redeclarations of virtual functions inside the CLxImpl_TextScriptInterpreter class.The ValidateFileType makes sure that the file we are being passed is of the correct format. The Run function takes the file we have been given and interprets it line by line.
The Init starts up our interpreter. However, on top of that it also adds all the functions that we declared in the header file and then defined in a separate cpp. These functions handle logging, options, and the progress bar. There is also a sort of master function which performs all the queries or executes. The Kill function simply shuts down our interpreter.
class CLuaInterpreter : public CLxImpl_TextScriptInterpreter
{
CLxUser_LogService logSvc;
CLxUser_CommandService cmdSvc;
CLxUser_ValueService valueSvc;
public:
virtual ~CLuaInterpreter () {}
virtual LxResult tsi_ValidateFileType (
ILxUnknownID scriptObj,
const char *firstLine) LXx_OVERRIDE;
virtual LxResult tsi_Run (
ILxUnknownID scriptObj,
int execFlags,
const char *args,
ILxUnknownID messObj) LXx_OVERRIDE;
void Init ();
void Kill ();
static LXtTagInfoDesc descInfo[];
private:
lua_State *L;
};
./Server_Tags¶
Servers tags are examined when the server is initialized, and give information about the server. We set the tags in this case by taking descinfo[] arrays and associating the relevant data with the corresponding flags.
The tags here indicate that the server we will be exporting has the name “Lua Scripts” and deals with files of the type .lua.
LXtTagInfoDesc CLuaInterpreter::descInfo[] = {
{ LXsSRV_USERNAME, "Lua Scripts" },
{ LXsLOD_DOSPATTERN, "*.lua" },
{ 0 }
};
The tags here indicate that CLuaInterpreter has the name Lua Scripts and takes files with the .lua extension.
./Initialize_(index)¶
Intialize is called when we add the plugin to modo, and is the utility that exports the server. The LXx_ADD_SERVER method is simply a wrapper that is identical to normal method of adding a server, with the arguments being (interface_to_be_added, class_you_depend_on, server_name).
This initialize function exports one server of the type TextScriptInterpreter that is dependent on the class CLuaInterpreter and has the name lua.
void
initialize ()
{
LXx_ADD_SERVER (TextScriptInterpreter, CLuaInterpreter, "lua");
}
Implementations¶
lxlua.cpp¶
Add a string to a parent log, possibly returning a log entry for sub-entries
1 2 3 4 5 6 7 8 9 10 | static void
AddLogStringEntry (
CLxLoc_LogEntry &parent,
const char *s,
LxResult code,
int persist,
CLxLoc_LogEntry &entry)
{
...
}
|
Adding a log entry to a parent, for clients with no need for the entry.
void
AddLogString (
CLxLoc_LogEntry &parent,
const char *s,
LxResult code,
int persist)
{
...
}
Logging for clients with no need for the entry.
void
LogString (
const char *s,
LxResult code,
int persist)
{
...
}
lxout: Output a string to the log
int
l_lxout(lua_State *L)
{
...
}
Internal function to perform queries and executions
#define LXEVALMODEf_QUERY 1 // Query only; fail if no query is marked
#define LXEVALMODEf_EXECUTE 2 // Execute only; fail if a query is marked
#define LXEVALMODEf_EITHER (LXEVALMODEf_QUERY | LXEVALMODEf_EXECUTE) // Query or execute, whatever works
LxResult
lxeval(lua_State *L, int mode)
{
...
}
At some point in the future, lxq() needs to use the raw string conversion feature to ensure that the values that are queried are the same kinds of values that get passed to commands.
int
l_lxq(lua_State *L)
{
...
}
lxqt(): Query a toggle command’s toggle argument. Returns the query state on success (1 or 0), or 0 on failure.
int
l_lxqt(lua_State *L)
{
...
}
Return true if the last command executed/queried successfully.
1 2 3 4 5 | int
l_lxok(lua_State *L)
{
...
}
|
Return the LxResult code of the last command executed or quieried.
int
l_lxres(lua_State *L)
{
...
}
When activated, lx() and lxq() data is output to the event log. If no args are passed in, this returns if tracing is active or not.
int
l_lxtrace(lua_State *L)
{
...
}
Get the state of an option.
int
l_lxoption(lua_State *L)
{
...
}
Get the state of an option.
int
l_lxsetOption(lua_State *L)
{
...
}
Initialize the progress bar. Initialize the progress bar with n total steps. Returns 0 on error.
int
l_lxmonInit(lua_State *L)
{
...
}
Step the progress bar. Increment the progress bar by n steps, or 1 step if no steps are provided. This always returns true unless the user aborts, in which case it returns false.
int
l_lxmonStep(lua_State *L)
{
...
}
verifies that the file passed in is of the lua type.
LxResult
CLuaInterpreter::tsi_ValidateFileType (
ILxUnknownID scriptObj,
const char *firstLine)
{
...
}</syntaxhighlight>
====intrlua.cpp====
adds all of the functions just implemented in lxlua.cpp to CLuaInterpreter
<syntaxhighlight>
void
CLuaInterpreter::Init()
{
...
}
performs most of the work, is the function that actually interprets the file.
LxResult
CLuaInterpreter::tsi_Run (
ILxUnknownID scriptObj,
int execFlags,
const char *args,
ILxUnknownID messObj )
{
...
}
This function cleans up.
void
CLuaInterpreter::Kill()
{
...
}