Lua/SWIG wrap userdata from within Lua - c++

I am using swig-lua. I have a function in Lua which I call and it returns me a pointer (userdata). right now I know what this pointer is, but how can I tell Lua from within Lua?

From the Lua Reference Manual:
setmetatable (table, metatable)
Sets the metatable for the given
table. (You cannot change the
metatable of other types from Lua,
only from C.)
You cannot "tell Lua" what a userdata is within Lua. It must be given a metatable or manipulated through bound function calls using the C API. See chapter 28.1 of Programming in Lua (Pil) for more information.

The very definition of userdata is that Lua does not, can not, and doesn't want to know what it is. It's your data- what it is is your problem. If you want to manipulate it, then you must call C functions with it (operator overloads available by metatable setting).

Tell SWIG about the data type pointed at by that void pointer. If SWIG is aware of the type, then it will pass it to Lua as a userdata with a suitable metatable attached that allows the Lua side to access and modify the individual data fields, (and if it is a class, call call its methods).
This might mean telling SWIG about some data types that aren't otherwise required by the library, but is probably worth the effort in the long run.
All Lua knows about what type a userdata is is contained in its metatable. Two userdata values are the same type if they have the same metatable. That metatable is responsible for mediating all access to the its content from the Lua side, and is usually made up of methods implemented in C so that is possible to do. Without such a metatable, then the Lua side can only treat a userdata as an opaque blob.

Related

Lua add a instance field to userdata with C++

I want to add some static fields to my Lua userdata objects coming from C++. The objects in question are vectors, they're created in C++ land and they work as they are but I've tried lua_setfield on my userdata but I get a attempt to index a Vector value error and I don't really want to have to use .x(), .y(), .z() due to the cost of having to call a function, push to stack and then read on the Lua side.
Is there any way to register fields on userdata for Lua access?
Userdata doesn't have "fields". What it can have is a metatable, for which you can define the __index and __newindex metamethods. Given such a metatable, the former function is called when reading the value of a field of the userdata, while the latter is called when assigning a value to a field from the outside (ud.some_field = 4 or an equivalent). If you want fields to be read only (to some degree), you can just implement __index, and attempts by the user to use __newindex will fail.
So in your C++ code, after creating the userdata, you can use lua_setmetatable to assign it a table that has these methods defined within it. Of course, these functions will need to access the actual C++ object from the userdata and fetch the specific values you're interested in.

Lua get function from argument

A simple example of producing.
protocol.onConnect(function() end, function () end, ...)
Now in c, i want to get the functions which are in args #1, #2.
In strings, numbers,... we can get them using (lua_getstring,..), But I at-least didn't found how to get a function.
int luaProtocolOnConnect(lua_State* L)
{
int base_func // func #1
int call_func // func #2
....
}
You cannot really "get" a Lua function. Lua functions, like Lua tables, are pure-Lua objects. As such, they have no C or C++ analog. If you want to call a Lua function, that's done through lua_call, lua_pcall or similar functions. This is done in-situ on the Lua stack.
So you can't take a Lua function and turn it into a C++ value. What you can do is take a Lua function and manipulate it in the various ways that all Lua objects can be manipulated.
For example, let's say you want to store a Lua function in a C++ object, then later call whatever Lua function was stored there. Well obviously, you can't convert the Lua function directly into a C++ value. What you can do is store that Lua function in a place which C++ can access. You use some value which does have a C++ analog to reference that stored Lua function. The value must be unique for every object you want to store like this. The value you get when storing the object will be saved in your C++ object. When the time comes to retrieve the Lua function, you simply use the stored value to retrieve it.
Because this is an exceedingly common operation, Lua has ways to facilitate this. The first is the Lua registry, a table that C++ can access but Lua code cannot (not unless you give it access).
The second is the luaL_ref series of functions. luaL_ref takes whatever is at the top of the stack and sticks it in a table you provide, returning to you an integer key that can be used to retrieve it later. lua_rawgeti can be used to retrieve the function from the table by the key, and luaL_unref takes the table and the integer key, removing the referenced function from the table when you're done with it.
So if you want to store such functions, you simply need to create such a table, stick it in a known place in the registry (so that you can fetch it whenever you need to), and then use luaL_ref to store those functions. When it comes time to call them, retrieve them with lua_rawgeti. When you're finished using them, destroy them with luaL_unref.
You can use lua_isfunction to check if it's a function, use lua_pushvalue to push its value on top of the stack and then use luaL_ref (luaL_ref(L,LUA_REGISTRYINDEX);) to turn it into a unique key you can later reference to retrieve the value (lua_rawgeti(L,LUA_REGISTRYINDEX,ref)) and call the function.

"Cast" the address of a Lua table to a Lua table

Say I have the address of a table - how would I "cast" a table variable to it? I'm not concerned about "bad practice" or crashes because this is just an individual problem.
I want to do something like
lua_table tab = *(lua_table*)0xaddr
...but within the Lua global environment.
I understand how bad this is but I really need to know if this is possible. It may not be the best way to do what I'm trying to do, but I'm quite certain it's the easiest and that it will work if this is possible. I am using Lua 5.1.4.
Lua exposes no API for doing this.
It would be easier and much more robust to fix your design rather than trying to force this to work.
In order to do what you're attempting, you must:
Get a pointer to the Lua table's data structure. I'm sure you believe that you already have such a pointer. But there's nothing in Lua that guarantees that the pointer you have obtained (through some means) is actually a pointer to the table data structure. It could be a pointer to something else. So you need to hunt through Lua's internals to make sure that wherever you're getting this pointer from is giving you a pointer to the actual object.
Find the correct type, declared within Lua's internals. There is some C type (Lua's written in C, not C++) that Lua uses to represent the main table data structure. You will have to track down this struct definition and use that.
A cursory examination of the Lua library suggests that the main table data structure is defined in lobject.h, under the name Table.
Find the internal APIs that Lua uses to manipulate this table correctly. It's obviously some kind of hash table, but you're going to need to use Lua's functions to actually do anything with it.
A cursory examination of Lua's internals suggests that this code would be found in ltable.h. However, there are probably more APIs than that. Also, do note that many of those APIs take a lua_State, so they may be doing some stack fiddling.
You will also need to look through Lua's API so that you can learn how to use them without breaking the table. Lua may have certain expectations about when certain functions are called or the order between them or whatever. Break these at your own peril.
Even then, this:
Table tab = *(Table*)0xaddr
Will never work. Or at least, not the way you mean for it to. Lua is written in C. Which means that Table is not going to work like a C++ value type. Copying it will only do a bitwise copy. So modifying tab will only modify your local copy of those values. If those are pointers to other data structures, that may be OK, since your pointers and the original pointers point to the same data structures. But if you perform some operation that changes the Table::flags field on the table, for example, the table stored in Lua will not be affected, only your local tab copy will be.
You have to manipulate the object as a pointer, not a copy of the original.
Table *tab = reinterpret_cast<Table*>(0xaddr);

Safely passing a intptr_t to Lua [duplicate]

I would like to know is there a way to pass a struct pointer to a lua script,
and reach it's members from lua without copy (for read and write purposes).
So, for example is it possible to overwrite a member of a c struct directly through of its pointer?
(I am using luajit)
In addition to Tim's answer, you can also go for light userdata. You don't end up with a copy of your data in the Lua stack, all you push to Lua is a pointer.
Lua has no understanding of what is in this pointer, whether it still points to valid memory, or how to access any objects in this pointer, so you'll have to handle all of this yourself in C. I am usually sending a pointer to an item on a list, so if there's any risk that entry has been deleted from the list, I first iterate over the list to validate the pointer (not a big deal if your lists are short). To access items within the pointer in Lua, you need to write get/set functions in C that you can call from Lua.
To get started, here are the entries on pushing and retrieving the lightuserdata:
lua_pushlightuserdata - push an entry on the stack
lua_touserdata - retrieve the pointer value
lua_islightuserdata - validate entry is light userdata
Programming in Lua entry on light userdata
Seeing as you have tagged this for luajit, you can combine the light userdata (as mentioned by others) with FFI for direct struct member access, see the tutorial here: http://luajit.org/ext_ffi_tutorial.html
The way to do this is with a lua userdata. Here are a couple examples: link, another link.

using a pointer from a C++ object, to another C++ object, to modify member variables, from Lua

How do you get a reference to a C++ object, from another C++ object, inside a Lua script? I don't really know how to summarize that in words properly, so let me elaborate with a Lua example first:
function doSomething()
compo = a:getComponent()
compo:setVariable(0)
end
a is a C++ object, and the function getComponent returns a pointer:
// inside A.h
Component* A::getComponent();
It seems the problem is that getComponent() is passing a copy of the Component object to Lua, instead of a reference. I come across the same problem with every function that returns a pointer, Lua cannot modify the original object.
Object a seems to be working correctly, if I modify a variable from within Lua, it's outcome is mirrored in C++. Both A and component are bound to Lua already, as well as the required methods.
Am I missing something syntactically or is there more to it than that?
I am using luabind, Lua 5.1, and MinGW. Thanks for any help in advance.
EDIT
Here is the luabind code. I summarized it because there's a bunch of other binds that have no relation to the problem:
luabind::class_<A>("A")
.def("getComponent", &A::getComponent)
Make a Lua wrapper for the "component" too. Then make a:getComponent() return the Lua object, not a real reference for the C++ object. Add any methods you need on that new wrapper object. If you have more "objects", rinse and repeat.
In short: for every object you want to manipulate from Lua, you will have to create a Lua wrapper. The only way around that is creating extra functions on the top level object, and calling those from Lua (a:setComponentVariable(0) instead of a:getComponent() + compo:setVariable(0)).