1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef TOOLS_TELEMETRY_LUA_INTERPRETER_LUA_ENGINE_H_ 18 #define TOOLS_TELEMETRY_LUA_INTERPRETER_LUA_ENGINE_H_ 19 20 #include <string> 21 #include <vector> 22 23 #include "lua.hpp" 24 25 namespace lua_interpreter { 26 27 // Encapsulates Lua script execution environment. 28 // Example: 29 // LuaEngine lua_engine; 30 // std::vector<std::string> script_output = 31 // lua_engine.ExecuteScript("print('2')") 32 class LuaEngine { 33 public: 34 // Creates a new instance of the LuaEngine. 35 LuaEngine(); 36 ~LuaEngine(); 37 38 // Loads Lua script provided as script_body string and invokes the Lua 39 // function corresponding to function_name, passing in the corresponding 40 // published_data and saved_state arguments as Lua tables. 41 // 42 // Returns the output from executing the given script. If loading or 43 // invocation are unsuccessful, the errors are returned in the output. 44 std::vector<std::string> ExecuteScript(std::string script_body, 45 std::string function_name, 46 std::string published_data, 47 std::string saved_state); 48 49 // Returns the saved state stored in the Lua registry of the LuaEngine 50 // instance, if any, in the form of a JSON string. 51 std::string GetSavedState(); 52 53 // Returns an allocated char** pointing to null-terminated equivalents 54 // of the strings within the vector passed in. 55 // Returns nullptr if the vector contains no elements. 56 // 57 // There is no std::vector<std::string> in C, so this type must be 58 // converted to a type usable by C, hence this utility function. 59 static char** StringVectorToCharArray(std::vector<std::string> vector); 60 61 private: 62 // Invoked by a running Lua script to produce a log to the output. This is 63 // useful for debugging. 64 // 65 // This method returns 0 to indicate that no results were pushed to Lua 66 // stack according to Lua C function calling convention. More info: 67 // https://www.lua.org/manual/5.3/manual.html#lua_CFunction Usage in lua 68 // script: 69 // log("selected gear: ", g) 70 static int ScriptLog(lua_State* lua); 71 72 // Invoked by a running Lua script to store intermediate results. 73 // The script will provide the results as a Lua table. The result pushed by 74 // Lua is then forwarded to the Lua registry. 75 // 76 // The IDE supports nested fields in the table, but the actual 77 // ScriptExecutor currently supports boolean, number, integer, string, and 78 // their arrays. Refer to 79 // packages/services/Car/packages/ScriptExecutor/src/LuaEngine.h for the 80 // most up to date documentation on the supported types. 81 // 82 // This method returns 0 to indicate that no results were pushed to Lua 83 // stack according to Lua C function calling convention. More info: 84 // https://www.lua.org/manual/5.4/manual.html#lua_CFunction 85 static int OnSuccess(lua_State* lua); 86 87 // Invoked by a running Lua script to effectively mark the completion of the 88 // script's lifecycle. The script will provide the final results as a Lua 89 // table. The result pushed by Lua is then forwarded to the 90 // output. 91 // 92 // The IDE supports nested fields in the table, but the actual 93 // ScriptExecutor currently supports boolean, number, integer, string, and 94 // their arrays. Refer to 95 // packages/services/Car/packages/ScriptExecutor/src/LuaEngine.h for the 96 // most up to date documentation on the supported types. 97 // 98 // This method returns 0 to indicate that no results were pushed to Lua 99 // stack according to Lua C function calling convention. More info: 100 // https://www.lua.org/manual/5.4/manual.html#lua_CFunction 101 static int OnScriptFinished(lua_State* lua); 102 103 // Invoked by a running Lua script to indicate that an error occurred. This 104 // is the mechanism for a script author to receive error logs. The caller 105 // script encapsulates all the information about the error that the author 106 // wants to provide in a single string parameter. The error is 107 // then forwarded to the output. 108 // 109 // This method returns 0 to indicate that no results were pushed to Lua 110 // stack according to Lua C function calling convention. More info: 111 // https://www.lua.org/manual/5.4/manual.html#lua_CFunction 112 static int OnError(lua_State* lua); 113 114 // Invoked by a running Lua script to produce a metrics report without 115 // completing the script's lifecycle, The script will provide the 116 // report as a Lua table. The report pushed by Lua is then forwarded to the 117 // output. 118 // 119 // on_metrics_report can also be used by a running Lua script to store 120 // intermediate results if the second argument is specified. The script 121 // will provide the results as a Lua table. The result pushed by Lua is then 122 // forwarded to the Lua registry. 123 // 124 // This method returns 0 to indicate that no results were pushed to 125 // Lua stack according to Lua C function calling convention. More info: 126 // https://www.lua.org/manual/5.4/manual.html#lua_CFunction Usage in lua 127 // script: 128 // on_metrics_report(report_as_a_table) 129 // on_metrics_report(report_as_a_table, saved_state_as_a_table) 130 static int OnMetricsReport(lua_State* lua); 131 132 // Saves the saved_state to the Lua registry of the lua_State. 133 static void SaveSavedStateToRegistry(lua_State* lua, std::string saved_state); 134 135 // Clears the current saved state in the Lua registry of the lua_State. 136 static void ClearSavedStateInRegistry(lua_State* lua); 137 138 // Maintains the state of Lua. 139 lua_State* lua_state_; 140 141 // Holds the metric reports and logs from the last script execution. 142 static std::vector<std::string> output_; 143 }; 144 145 // Adds compatibility with Python. 146 // Since Python is written in C, the external functions must be C callable (so 147 // C++ types must be converted to C compatible types). These are the functions 148 // that can be directly called on by the Python ctypes library. 149 extern "C" { 150 151 // Holds information about the output of the execution. 152 struct LuaOutput { 153 // Holds the metric reports and logs from the last script execution. 154 char** output; 155 156 // Details how many strings are within output. 157 // 158 // The output array doesn't have size information attached so 159 // the size of the array must be encoded in the struct for iteration (or risk 160 // Segmentation Faults from accessing random data). 161 int size; 162 163 // Holds the saved state of the script execution, if any, 164 // in the form of a JSON string. 165 char* saved_state; 166 }; 167 168 // Frees up the memory used by the lua_output. 169 void FreeLuaOutput(LuaOutput* lua_output); 170 171 // Creates a new instance of the LuaEngine. 172 LuaEngine* NewLuaEngine(); 173 174 // Loads Lua script provided as script_body string and invokes the Lua 175 // function corresponding to function_name, passing in the corresponding 176 // published_data and saved_state arguments as Lua tables. 177 // 178 // Allocates and returns the output from executing the given script in the 179 // form of the LuaOutput struct. If loading or invocation are unsuccessful, the 180 // errors are returned in the output. 181 LuaOutput* ExecuteScript(LuaEngine* l, char* script, char* function_name, 182 char* published_data, char* saved_state); 183 } // extern "C" 184 } // namespace lua_interpreter 185 186 #endif // TOOLS_TELEMETRY_LUA_INTERPRETER_LUA_ENGINE_H_ 187