After the program logic is handed over to the script for running, the C/C ++ layer only needs to pass necessary input information into the virtual machine. Of course, we also need an efficient transfer method.
Taking the passing of mouse coordinates to the Lua virtual machine as an example, we can easily think of a way to define a C function get_mouse_pos. You can call this function when you need to obtain the mouse coordinates in the Lua script.
But this is not a good method, because every time you get the mouse coordinates, You need to perform a switch between the virtual machine and the native code. We should look for more efficient solutions.
The person who writes the script can get the mouse coordinates only once, and then put the data into a group of global variables. In a running part, the get_mouse_pos function is no longer called, but the cursor position is obtained by accessing global variables.
From this solution, we can extend that, in fact, this global variable can be automatically set by the C program. After the Windows message is processed in the native code running film, set the mouse information directly to the Lua virtual machine. The code is similar.
lua_pushstring(L,"MOUSE_X"); lua_pushnumber(L,mouse_x); lua_settable(L,LUA_GLOBALSINDEX); lua_pushstring(L,"MOUSE_Y"); lua_pushnumber(L,mouse_y); lua_settable(L,LUA_GLOBALSINDEX);
However, there is still a efficiency problem, that is, lua_pushstring. We know that in the Lua virtual machine, every time a string is generated, we need to check whether the same copy of the string exists in the Virtual Machine. If so, we can directly reference the existing one. If not, A new copy is generated.
Here, both the mouse_x and mouse_y strings exist in the Lua Virtual Machine except for the first run. Although New strings are not generated, searching and comparing strings still consume a certain amount of time. Next, we will optimize this lua_pushstring operation.
We can create these two strings at the beginning of the program and keep references in C.
lua_pushstring(L,"MOUSE_X"); _mouse_x_ref=lua_ref(L,-1); lua_pushstring(L,"MOUSE_Y"); _mouse_y_ref=lua_ref(L,-1);
Then, you do not need to perform the lua_pushstring operation later, but change it to a relatively fast lua_getref operation.
lua_getref(L,_mouse_x_ref); lua_pushnumber(L,mouse_x); lua_settable(L,LUA_GLOBALSINDEX); lua_getref(L,_mouse_y_ref); lua_pushnumber(L,mouse_y); lua_settable(L,LUA_GLOBALSINDEX);
Lua_getref is faster because Lua optimizes the key table operation on the number and directly performs a pointer operation. The ref is recorded in a global table. In addition, lua_getref does not require the strcmp operation performed by lua_pushstring.
So there is no room for optimization for this method? There are still some answers.
We can actually write a Lua program and put it in a separate file (mouse. Lua). The program is very short:
Return funtion (MX, my) mouse_x, mouse_y = Mx, my end
We run it when the program starts.
lua_dofile(L,"mouse.lua"); _mouse_set_ref=lua_ref(L,-1);
You can perform the following operations when setting the mouse coordinates:
lua_getref(L,_mouse_set_ref); lua_pushnumber(L,mouse_x); lua_pushnumber(L,mouse_y); lua_call(L,2,0);
In this solution, only the ref of a function needs to be retained, and the setting work is handed over to the pseudo commands in the virtual machine. From this example (only mouse_x and mouse_y are the information to be transmitted), it does not indicate that the latter is more efficient. After all, lua_call also consumes more resources. However, the last solution is more flexible, which is more concise for the exchange of native code to more data from virtual machines.
For PS. lua_ref, remember to call lua_unref to unreference it.
1