I have a C++ project, where 1 method of a 1 class changes very often. So I want to take that code from C++ to Lua. Note, I'm novice to Lua.
The whole task:
Bind some class methods to Lua state machine;
Pass reference to class object to a function, written in Lua;
Operate with passed C++ object in Lua function.
I've found how to make first step with Lunar, and can't cope with second and third.
I can't use SWIG and boost.
//This has a large number of steps, but I'm gonna post them all. This is all using native Lua 5 and the lua CAPI.
int CreateInstanceOfT(lua_State* L) {
new (lua_newuserdata(L, sizeof(T))) T(constructor args);
return 1;
}
int CallSomeFuncOnT(lua_State* L) {
if (lua_istable(L, 1)) { // If we're passed a table, get CData
lua_getfield(L, 1, "CData");
lua_replace(L, 1);
}
if (!lua_touserdata(L, 1))
lua_error(L); // longjmp out.
T& ref = *(T*)lua_touserdata(L, 1);
ref.SomeFunc(); // If you want args, I'll assume that you can pass them yourself
return 0;
}
int main() {
lua_State* L = luaL_newstate();
lua_pushcfunction(L, CreateInstanceOfT);
lua_setglobal(L, "CreateInstanceOfT");
lua_pushcfunction(L, CallSomeFuncOnT);
lua_setglobal(L, "CallSomeFuncOnT");
luaL_dofile(L, "something.lua");
lua_close(L);
}
-- Accompanying Lua code: semicolons are optional but I do out of habit. In something.lua
function CreateCInstance()
local Instance = {
CData = CreateInstanceOfT();
SomeFunc = CallSomeFuncOnT;
}
return Instance;
end
local object = CreateCInstance();
object:SomeFunc(); // Calls somefunc.
I could post a great quantity of detail about how to make exposure easier, and how to make inheritance, and suchlike - and it'll need altering if you want to expose more than one T (I think the most common solution is a simple struct { std::auto_ptr<void>, int type } deal). But, it should be a starting point if you don't understand anything about this process.
Bascally, first, we ask Lua to allocate some space (the userdata), then put T in it. When CallSomeFuncOnT comes up, first we ask it if we have a table (many Lua classes are based around tables, as they support object orientation, metatables, and such), and get the userdata out, which we then convert into a pointer to our object, and then convert into a reference. Remember that lua_touserdata gives you a void*, so you'd better be damn sure about what's on the other end. Then we call somefunc and return.
In Main, we just register the functions as globals.
Now, in Lua, when you call CreateInstanceOfT, it effectively just calls the T constructor, transparently to the Lua user. Then we ditch it in a table, which is simpler for Lua novices, and call SomeFunc by passing it this table.
Have you taken a look at luabind? It makes it fairly easy to expose C++ objects and functions to LUA.
Like John, I've used luabind and recommend it. However, since using boost isn't an option for you, you may find the list of libraries on this page helpful. You may also want to check out the DoItYourselfCppBinding page on the lua-users wiki.
One library mentioned on the page is oolua, which has no dependencies (so it says).
Related
I have an object created in c++, I want to pass it to Lua, in Lua i need get that object and pass to c++.
in c++:
class Measure
{
public:
Measure();
private:
int value;
}
Void PassObjToLua(lua_State *L)
{
Measure * m=new Measure(); // I need to pass this object to Lua
// How to implement?
}
Void GetObjFromLua(lua_State *L)
{
//I need to get Measure object from Lua. How to implement?
}
In Lua script.
Local measure=nil;
measure= PassObjToLua();
GetObjFromLua(measure);
What do i need to do?
The best way I know of is the Sol library, which exposes a C++ interface.
Its userdata example shows how the library can be used to create tables linked to the C++ objects.
This answer might look like it's link-only, but you only really need to take a peek at how complicated the library is to realize that the question can't really be answered in one, simple answer. There are numerous caveats with regard to using the C API and wrapping it in C++ primitives.
I personally dislike the macro-based reflection-like binders and would recommend against using one, altough of course other people might have different opinions.
As Marcus wrote, you need to use the Lua C API in some way. To do it, you can either use a C code generator, or a Lua wrapper. You have examples of both on the lua wiki site, as well as instructions on how to write your own Lua wrapper.
EDIT: To expand my answer a bit. You need to represent a C++ class type instance as a lua type instance. The 2 options that are most popular are: representing a C++ object as a lua table or a lua userdata with a metatable attached. If you choose to use a lua table, you have the options of filling the table with keys, that are mapped to CFunctions, or use a metatable just as with userdata. A metatable allows you to hook table/uservalue key accesses and process them in C++.
You can use Lua's light user data to do that. In that case, the object is managed by C++ :
extern "C" int PassObjToLua(lua_State *L)
{
Measure * m=new Measure(); // I need to pass this object to Lua
lua_pushlightuserdata (L, m);
return 1;
}
extern "C" int GetObjFromLua(lua_State *L)
{
Measure *m = (Measure*)lua_touserdata (L, 1);
return 0;
}
To register your C functions in the Lua context :
lua_pushcfunction (L, GetObjFromLua);
lua_setglobal (L, "GetObjFromLua");
lua_pushcfunction (L, PassObjToLua);
lua_setglobal (L, "PassObjToLua");
Lualib has a C interface, not a C++ one -- so without further ado, you'd have to generate extern C functions that you can use with Lua.
The place here is far too short to give you a complete introduction on how to use C++ with lua, or evn how to extend a C program with Lua. I think it's safe to say you will find a tutorial that fits exactly your needs when you use google with lua C interface.
EDIT: Here's a screenshot of my google search. How much more ridiculous can we get?
For a project I'm working on, I need to expose some C++ classes in another library to Lua. Unfortunately, one of the most important classes in this library has lots of Unions and Enums (the sf::Event class from SFML), and from a quick Google search I've discovered there is nothing on exposing C++ Unions to Lua. I don't mind if it's being exposed with the Lua/C API, with a library or with a binding generator, as long as it works. But, I'd prefer not to use a binding generator, because I want to be able to create an object in C++, then expose that instance of the object to Lua (unless that's possible with a binding generator)
For registering C/C++ functions you need to first make your function look like a standard C function pattern which Lua provides:
extern "C" int MyFunc(lua_State* L)
{
int a = lua_tointeger(L, 1); // First argument
int b = lua_tointeger(L, 2); // Second argument
int result = a + b;
lua_pushinteger(L, result);
return 1; // Count of returned values
}
Every function that needs to be registered in Lua should follow this pattern. Return type of int , single parameter of lua_State* L. And count of returned values.
Then, you need to register it in Lua's register table so you can expose it to your script's context:
lua_register(L, "MyFunc", MyFunc);
For registering simple variables you can write this:
lua_pushinteger(L, 10);
lua_setglobal(L, "MyVar");
After that, you're able to call your function from a Lua script. Keep in mind that you should register all of your objects before running any script with that specific Lua state that you've used to register them.
In Lua:
print(MyFunc(10, MyVar))
Result:
20
I guess this could help you!
If you are willing to use boost::variant rather than a union, you could try using my LuaCast library.
I'll try to add unions as a base type as well.
Maybe I am bad at Google Searching, maybe I try to over think things, but if I have this Lua class:
--Foo:
Foo = {number = 0}
function Foo.setNumber(newNumber)
number = newNumber
end
If I try to use this class in another .lua file, after the file ends, the object is destroyed. Other tutorials I've seen using Lua (like here) assume that the C++ program already knows about the class so it is defined like a normal C++ class. In my case however, the point of Lua is so that the C++ program is only a framework that handles drawing and such, so can't have Lua classes that are hard-coded into the program.
So, my question is, how can I define and keep a Lua object, using Lua, but the object isn't destroyed unless I specifically tell it to? I was considering creating a class in C++ that stores a vector/map of Lua objects, then the Lua script can request a object using a exposed function. Unfortunately that sounds very slow because for Lua to execute one function, it needs to receive a copy of the class from C++, call the function of the class, then send it back to C++ for it to overwrite the previous copy.
Here is some code that is modified from Elias Daler's tutorials on how I'm running Lua scripts (which are very good IMO):
#include <lua.hpp>
#include <LuaBridge.h>
#include <string>
//Example class to expose (I realise it's very similar to Foo):
class Bar
{
private:
std::string string;
public:
void setString(const std::string& newString) {string = newString;}
}
int main()
{
//Expose the API:
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luabridge::getGlobalNamespace(L)
.beginClass<Bar>("Bar")
.addConstructor<void(*)(void)>()
.addFunction("setString", &Foo::setString)
.endClass();
//Run the script:
luaL_dofile(L, "script.lua");
luaL_openlibs(L);
lua_pcall(L, 0, 0, 0);
return 0;
}
In Lua, all the global variables are stored in the global table _G (called environment). Unless someone modifies it explicitly, it is destroyed only when the Lua state is destroyed.
So, you can run the second script with:
luaL_dofile(L, "another_script.lua");
And it should see the global variables left by the first script, because the script uses the same Lua state as the first one.
Lua manages its own lifetimes through garbage collection. If it can't see an object is used, it will destroy it. The trick is to store these objects in a lua table, with the c++ adding and removing them, controlling their life time.
I'm fairly new to Lua, I've been working on trying to implement Lua scripting for logic in a Game Engine I'm putting together. I've had no trouble so far getting Lua up and running through the engine, and I'm able to call Lua functions from C and C functions from Lua.
The way the engine works now, each Object class contains a set of variables that the engine can quickly iterate over to draw or process for physics. While game objects all need to access and manipulate these variables in order for the Game Engine itself to see any changes, they are free to create their own variables, a Lua is exceedingly flexible about this so I don't forsee any issues.
Anyway, currently the Game Engine side of things are sitting in C land, and I really want them to stay there for performance reasons. So in an ideal world, when spawning a new game object, I'd need to be able to give Lua read/write access to this standard set of variables as part of the Lua object's base class, which its game logic could then proceed to run wild with.
So far, I'm keeping two separate tables of objects in place-- Lua spawns a new game object which adds itself to a numerically indexed global table of objects, and then proceeds to call a C++ function, which creates a new GameObject class and registers the Lua index (an int) with the class. So far so good, C++ functions can now see the Lua object and easily perform operations or call functions in Lua land using dostring.
What I need to do now is take the C++ variables, part of the GameObject class, and expose them to Lua, and this is where google is failing me. I've encountered a very nice method here which details the process using tags, but I've read that this method is deprecated in favor of metatables.
What is the ideal way to accomplish this? Is it worth the hassle of learning how to pass class definitions around using libBind or some equivalent method, or is there a simple way I can just register each variable (once, at spawn time) with the global lua object? What's the "current" best way to do this, as of Lua 5.1.4?
One approach is to use
a lightuserdata pointing to the C++ variable
a C function to access the C++ variable using the lightuserdata
keep the lightuserdata as an upvalue of the C function so one function suffices for all variables
use the number of arguments to the function to select between getting and setting the variable
For example:
int game_state_var_accessor (lua_State *L)
{
int *p = lua_topointer(L, lua_upvalueindex(1));
if (lua_gettop(L) == 0)
{ // stack empty, so get
lua_pushinteger(L, *p);
return 1;
}
else
{ // arg provided, so set
*p = lua_tointeger(L,1);
return 0;
}
}
When you make a new game state you can create accessors for each variable using:
lua_pushlightuserdata(L, (int *)p); // where p points to your variable
lua_pushcclosure(L, game_state_var_accessor, 1);
The accessor is now on the stack and can be bound to a global name, or to the name of a method in a Lua class. If your Lua class table is on the stack at index t this would be:
lua_setfield(L, t, "name_of_accessor");
I have a class that is wrapped with swig, and registered with lua. I can create an instance of this class in a lua script, and it all works fine.
But say I have an instance of a class made in my c++ code with a call to new X, and I have la lua_state L with a function in it that I want to call, which accepts one argument, an instance of X... How do I call that function. Here is (some) of the code in question (I've omitted the error handling stuff):
main.cpp
class GuiInst;
extern "C"
{
int luaopen_engine (lua_State *L);
}
int main()
{
GuiInst gui=new GuiInst;
lua_State *L=luaL_newstate();
luaopen_engine(L); //this is swigs module
int error=luaL_loadfile(L,"mainmenu.lua")||
lua_pcall(L, 0, 0, 0);
lua_getglobal(L,"Init");
//Somehow push gui onto lua stack...
lua_pcall(L, 1, 0, 0));
lua_close(L);
}
mainmenu.lua
function Init(gui)
vregion=gui:CreateComponent("GuiRegionVertical");
end
At the moment all I have found that can work is to expose some functionality from the swig generated cpp file, and call that. This is bad for a few reasons... It won't work if I have multiple modulles and I had to change the default linkage specification in the swig file (using -DSWIGRUNTIME=).
I add the following to main.cpp
extern "C"
{
struct swig_module_info;
struct swig_type_info;
int luaopen_engine (lua_State *L);
swig_module_info *SWIG_Lua_GetModule(lua_State* L);
void SWIG_Lua_NewPointerObj(lua_State* L,void* ptr,swig_type_info *type, int own);
swig_type_info *SWIG_TypeQueryModule(swig_module_info *start,swig_module_info *end,const char *name);
}
//and then to push the value...
SWIG_Lua_NewPointerObj(L,gui,SWIG_TypeQueryModule(SWIG_Lua_GetModule(L),SWIG_Lua_GetModule(L),"GuiInst *"),0);
That gets a pointer to the module, then a pointer to the type, then calls swigs function to register it. It was an unreasonable thing to have to dig into a file that's not supposed to be human readable (so it says at the top of the file) and is just MESSY! (but it does work!)
Surely theres a better way to accomplish what I'm trying to do.
PS from a high level pov what I want is to have lua not refcount the Gui components which are created by the Object Factory in GuiInst, in case I'm going about this wrong. This is my first time exposing functionality to a scripting language apart from some very simple (and non-swig) python modules, so I'm prepared to take advice.
Thanks for any advice!
Response to comment by RBerteig
GuiInst's contructor is #defined to private when swig runs to prevent lua constructing instances of it, so that won't work for me. What I was trying to prevent was the following (in lua):
r=engine.GuiRegionVertical()
r:Add(engine.GuiButton())
which would call "g=new GuiButton" then register it with the GuiRegionVertical (which needs to store a pointer for various reasons), then call "delete g", and the GuiRegionVertical is left with a dangling pointer to g.
I suspect what really needs to happen is that GuiRegionVertical::Add(GuiButton*) should increment the ref count of the GuiButton*, and then GuiRegionVertical's destructor should decrement the refcounts of all of its contents, though i'm not sure how this should be done with swig.
That would remove the need for the private constructors, the Gui Object Factory and the nasty externs.
Am I going about this Wrong?
Thanks.
Better late then never, and this solution will help other people.
void handle_web_request(WebRequest *request, WebResponse *response)
{
lua_getfield(rackam->lua_state, LUA_GLOBALSINDEX, "handle_web_request");
SWIG_Lua_NewPointerObj(rackam->lua_state, request, SWIGTYPE_p_WebRequest, 0);
SWIG_Lua_NewPointerObj(rackam->lua_state, response, SWIGTYPE_p_WebResponse, 0);
lua_call(rackam->lua_state, 2, 0);
}
this code must be inside %{}% blocks in your .i file, because SWIGTYPE_p_WebRequest is
#define SWIGTYPE_p_WebResponse swig_types[6]
and swig_types[6] is
static swig_type_info *swig_types[12];
which means that swig_types is only accessable from the C++ file from which it is defined.
this particular snippet is sending in two of my wrappered pointers, so calling handle_web_request(request, response) from the C++ side of things will run the global lua function "handle_web_request" and pass it my two pointers, with the SWIG magic applied.
There is a simple and direct answer, that may not be the most efficient answer. SWIG produces wrappers for manipulating objects from the scripting language side. For objects, it also synthesizes a wrapped constructor. So, the direct solution is to just let the Lua interpreter call SWIG's constructor to create the new object.
For the wrapped engine.GuiInst class, you almost certainly can do something like:
int main()
{
lua_State *L=lua_open();
luaopen_engine(L); //this is swigs module
int error=luaL_loadfile(L,"mainmenu.lua")||
lua_pcall(L, 0, 0, 0);
luaL_dostring(L, "Init(engine.new_GuiInst())");
lua_close(L);
}
For a one-shot case like script startup, the penalty of running a string constant through luaL_dostring() is not bad at all. I'd look harder to avoid it in an event callback or an inner loop, however.
It does seem like there ought to be a way to convert a pointer directly into a wrapped object, I'm not spotting it in my own handful of SWIG generated wrappers.
Edit: Of course, the Lua fragment can be decomposed to API calls that get the engine table global on the stack, extract from it the new_GuiInst member, call it, then call the global Init, but the little bit of efficiency comes at the cost of some clarity.
As for dealing with objects that shouldn't be constructed by accident in user code, as the clarified question indicates, my first impulse would be to let SWIG generate the constructor function, keep a private reference if needed later, and remove it from the table. Even a C module is (usually) just a table whose members contain function values. Being implemented in C doesn't make them read-only unless extra effort is taken.
So, you could always retrieve the value of engine.new_GuiInst and park it in the registry (see luaL_ref() and the discussion in section 3.5 of the Lua Reference Manual of the pseudo-index LUA_REGISTRYINDEX for the details) for later use. Then, before letting any user code run, simply do the equivalent of engine.new_GuiInst = nil. I should note that for the C data types I've been playing with most recently, SWIG created two constructors for each type, named new_TYPE and TYPE. Both were visible in the module's table, and you would want to set both names to nil. If have much less experience with SWIG wrapping C++ classes, and the result may differ...
You might want to check and review the whole content of the engine table returned by SWIG, and create a proxy object that contains only the methods you want available to your users. You can also change the environment seen by the user script so that it only has the proxy available, and names the proxy engine as well. There has been a fair amount of discussion of sandboxing user scripts on the Lua list and at the lua-users wiki.