I am embedding Lua in a C++ application.
I have some modules (for now, simple .lua scripts) that I want to load programmatically, as the engine is being started, so that when the engine starts, the module(s) is/are available to scripts without them having to include a require 'xxx' at the top of the script.
In order to do this, I need to be able to programmatically (i.e. C++ end), ask the engine to load the modules, as part of the initialisation (or shortly thereafter).
Anyone knows how I can do this?
Hmm, I just use the simple approach: My C++ code just calls Lua's require function to pre-load the Lua scripts I want preloaded!
// funky = require ("funky")
//
lua_getfield (L, LUA_GLOBALSINDEX, "require"); // function
lua_pushstring (L, "funky"); // arg 0: module name
err = lua_pcall (L, 1, 1, 0);
// store funky module table in global var
lua_setfield (L, LUA_GLOBALSINDEX, "funky");
// ... later maybe handle a non-zero value of "err"
// (I actually use a helper function instead of lua_pcall
// that throws a C++ exception in the case of an error)
If you've got multiple modules to load, of course, put it in a loop... :)
The easiest way is to add and edit a copy of linit.c to your project.
Related
If I had a lua script, say
print'hi'
How would I get the lua bytecode equivalent to it using c++? I'm not sure if I'm explaining this right though. Thanks for all your help!
You need to load a script and then dump its bytecode.
The relevant C API functions are luaL_loadfile or luaL_loadstring for loading (they use the primitive lua_load) and lua_dump for dumping.
Loading is easy to do with these helper functions.
Dumping is a bt more work because of the need to provide a writer function. It may be easier to call string.dump after loading:
// load script, leave function on the stack
lua_getglobal(L,"string");
lua_getfield(L,"dump");
lua_pushvalue(L,-3);
lua_call(L,1,1);
// string containing bytecode left on the stack
What is the correct way to go about automatically running some setup code (either in R or C++) once per package loading? Ideally, said code would execute once the user did library(mypackage). Right now, it's contained in a setup() function that needs to be run once before anything else.
Just for more context, in my specific case, I'm using an external library that uses glog and I need to execute google::InitGoogleLogging() once and only once. It's slightly awkward because I'm trying to use it within a library because I have to, even though it's supposed to be called from a main.
Just read 'Writing R Extensions' and follow the leads -- it is either .onAttach() or .onLoad(). I have lots of packages that do little things there -- and it doesn't matter this calls to C++ (via Rcpp or not) as you are simply asking about where to initialise things.
Example: Rblpapi creates a connection and stores it
.pkgenv <- new.env(parent=emptyenv())
.onAttach <- function(libname, pkgname) {
if (getOption("blpAutoConnect", FALSE)) {
con <- blpConnect()
if (getOption("blpVerbose", FALSE)) {
packageStartupMessage(paste0("Created and stored default connection object ",
"for Rblpapi version ",
packageDescription("Rblpapi")$Version, "."))
}
} else {
con <- NULL
}
assign("con", con, envir=.pkgenv)
}
I had some (not public) code that set up a handle (using C++ code) to a proprietary database the same way. The key is that these hooks guarantee you execution on package load / attach which is what you want here.
I use Lua for my game engine logic. My main game loop is not done in Lua. Only special nodes in my scene hierarchy have Lua scripts attached. These scripts are executed every frame. The problem I face is that I need to keep global variable values from one frame to another.
My temporary solution looks like this:
finish = useBool("finish", false)
timer = useInt("timer", 0)
showTimer = useBool("showTimer", true)
startTimer = useInt("startTimer", 0)
play0 = useBool("play0", false)
play1 = useBool("play1", false)
play2 = useBool("play2", false)
play3 = useBool("play3", false)
delta = useInt("delta", 0)
gameOverTime = useInt("gameOverTime", 5000)
finishTime = useInt("finishTime", 5000)
checkPoint = useInt("checkPoint", 255)
<...> Game logic <...>
setInt("message", message);
setInt("checkPoint", checkPoint)
setInt("finishTime", finishTime)
setInt("gameOverTime", gameOverTime)
setInt("timer", timer)
setBool("play3", play3)
setBool("play2", play2)
setBool("play1", play1)
setBool("play0", play0)
setInt("startTimer", startTimer)
setBool("showTimer", showTimer)
setInt("timer", timer)
setBool("finish", finish);
I call special methods that retrieve global variables from hash maps in C++ at the beginning and I set them again at the end of the script.
Is there a way to do this implicitly?
Is it a bad design to use Lua not as the main game loop?
Well, while there is nothing technically wrong with your solution, you might start to notice some performance issues if you end up with a lot of global variables (something you should, in general, avoid).
With that said, there is room for improvement. For example:
At the beginning of the script, check if your global variable is nil. If it is, then you can initialize it, if not, this is probably not the first time you're running the script, so leave it unmodified. But that means a lot of pesky if-else statements, which one can easily forget about. We can do better!
I would recommend looking at Chapter 14: The Environment, from the Programming in Lua book. Here's a quick quote from the intro:
Lua keeps all its global variables in a regular table, called the environment. ... The other (actually the main) advantage is that we can manipulate this table as any other table. To facilitate such manipulations, Lua stores the environment itself in a global variable _G. (Yes, _G._G is equal to _G.)
Since _G is a table, it also has a metatable, so you can define __index and __newindex metamethods to handle access to and creation of global variables. You can find examples of this in section 14.2. Go read the whole chapter, it's not that long (if you're unfamiliar with metamethods and metatables, also look through chapter 13 - this is where Lua really shines in terms of flexibility).
Now that we've covered the trivial and normal methods, let's look at the overkill end of the spectrum. As an example I'll look at Unity's approach to scripting. A Unity javascript usually defines variables, functions, and types. Any variables defined outside of the scope of methods or types are persisted between frames because the script itself is not executed every frame. Instead, they let the script define functions and call the functions at the appropriate time. So if you want something executed every frame - you put it in the Update function. Every script can define it's own Update function because it has it's own scope. So every frame the scripting engine goes through all objects, checks if the script's scope has an Update method and calls it.
Back to Lua - a solution like this would involve creating separate environments for each object/script/whatever your node is. Then, instead of executing the script attached to your node every frame, your main loop will go through all the nodes and run a function inside of their environment. You can also switch environments, so you can set the global environment to your node's env before executing it, and then switch back when you're done. This allows your scripts to use globals as they see fit, have them persisted between frames and excludes the possibility of name collisions or global namespace pollution. Additionally you can use metamethods to nest the node's environment inside the actual global environment or inside an API environment with helper methods (basically, if __index does not find something it looks it up in a parent).
I'm working on improving the way we handle Lua scripting for robot players in Bitfighter. Currently, each robot gets its own L instance, and we're trying to get them to all share one by swapping out environment tables. Note that bots may be completely different scripts.
I realize that this method is deprecated in Lua 5.2, but we are currently using lua-vec, which still uses Lua 5.1. The game is written in C++.
So...
First we create an environment, and call it :
// Create a table with room for 0 array and 1 non-array elements
lua_createtable(L, 0, 1); // -- tab
// Set the globals table to handle any requests that the
// script's environment can't
lua_pushstring(L, "__index"); // -- tab, "__index"
lua_pushvalue(L, LUA_GLOBALSINDEX); // -- tab, "__index", _G
// Set table["__index"] = _G, pops top two items from stack
lua_settable(L, -3); // -- tab
// Store the new table in the retistry for future use
lua_setfield(L, LUA_REGISTRYINDEX, name); // -- <<empty stack>>
Later, we load some Lua code, and recall the environment table:
luaL_loadfile(L, "luascripts.lua");
lua_getfield(L, LUA_REGISTRYINDEX, name); // -- function, table
lua_setfenv(L, -2); // -- function
Then run the loaded code:
lua_pcall(L, 0, 0, 0);
When the loaded Lua tries to use a basic function, such as print, it fails with the error:
attempt to call global 'print' (a nil value)
But, the script can do the following:
__index["print"](12)
So... why can't we access print directly? What are we missing? Or is there a fundamentally better way to run multiple scripts in the same Lua instance?
Your code is close to correct, but contains several issues - You are attempting to do something that won't work, and your attempt did the wrong thing in the wrong way..
You are setting the function environment of the function to a table which looks like this:
{__index = _G}
Naturally, when you attempt to access print, it is not found in this table.
From your comments, I infer that actually wanted to set the __index field of the metatable of the environment table. That is, you wanted to make the environment tables be like t in the example below:
t = {}
setmetatable(t, {__index = _G})
(The C++ translation of this is fairly straightforward).
Don't do this. It will solve your immediate problem, but it will not provide sufficient sandboxing. Consider for example a script like this:
table.sort = 10
"table" will be found by in _G by the metatable event handler. sort is just an element of the table table, and so can be replaced with impunity. Now, other scripts will be unable to sort tables with table.sort.
One way to perform this kind of separation is to mediate access to all the global values through some sort of (possibly recursive) userdata with hand-written handlers for the relevant metatable events. (This way probably has the most potential for performance and control, but could be difficult to implement).
Another way is to create an environment table for for each script, and to copy the safe/sandboxed elements from the global table into this environment table (so that each script has a totally separate version of all the mutable elements of the global table).
I'm sorry I don't have time to properly explain my suggested solutions to your problem. I hope that I have given you somewhere to start. Feel free to come back and edit this to include the solution that you ultimately use.
I have a need to create a Tcl extension that calls a managed .NET DLL/Class Library. Currently, the structure of my application is Tcl > DLL Wrapper (C++ CLR) > .NET Class Library (VB.NET), where ">" represents a function call.
My VB.NET DLL just takes a value and returns it back, keeping it simple for now. In the end, this will do some more advanced stuff that makes use of some .NET functionality.
Public Class TestClass
Public Function TestFunction(ByVal param As Integer) As Integer
Return param
End Function
End Class
My Tcl Extension (C++ CLR) creates an object of the type above
int TestCmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
// Check the number of arguments
if (objc != 2) {
Tcl_WrongNumArgs(interp, 0, objv, "arg");
return TCL_ERROR;
}
int param, result;
if (Tcl_GetIntFromObj(interp, objv[1], ¶m) != TCL_OK)
return TCL_ERROR;
SimpleLibrary::TestClass^ myclass = gcnew SimpleLibrary::TestClass(); //System.IO.FileNotFoundException
result = myclass->TestFunction(param);
Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
return TCL_OK;
}
And finally, my Tcl script loads the extension and calls the function.
load SimpleTclExtension.dll
TestCmd 2
If my VB.NET DLL is in the same directory as my extension DLL, the extension crashes when it instantiates a TestClass object. I've noticed if the VB.NET DLL is relocated to C:\Tcl\bin, the extension will find it, and TestCmd can be called just fine. The problem is that this will eventually need to be deployed across a number of PCs, and it's preferred not to mingle my application's files with another application's.
It seems like there should be some configuration settings that will fix this problem, but I'm not sure where. Any help is greatly appreciated.
Firstly, depending on just what kind of Tcl application you are using you may want to look at Eagle which is a implementation of Tcl in CLR.
I think you are bumping into .Net's desire to only load assemblies from your application's directory or its immediate subdirectories. The application here is the tclsh/wish executable which is why moving the .Net assembly makes it load. This is something you can fix with suitable manifests or calls to the API to permit assembly loading from alternate locations. In this case I think you will need to run some initialization code in your Tcl extension when it gets loaded into the Tcl interpreter to init the CLR and add the extensions location as a suitable place to load assemblies from. It has been a while since I was looking at this so I forgot the details but I think you want to look at the AppDomain object and check the assembly loading path properties associated with that or its child objects. Try AppDomain.RelativeSearchPath
To be more specific, Eagle includes Garuda which is a Tcl extension built specifically to allow calling .Net from Tcl