3
\$\begingroup\$

I store an object by a function call from Lua to C++ in first script in my application and after that I'll try to pass that object to other scripts and vice versa.

A part of script class in C++:

void script::set_property(lua_State* L, luabind::argument const& value)
{
  this->property_field = luabind::object(L, value);
}

luabind::object script::get_property(lua_State* L)
{
  return this->property_field;
}

Then in my script which is Script1.lua I do this:

script1:set_property(a table or a userdata or a string)
print(type(script1:get_property()))

The problem is, values sent by scripts are distinct in different Lua states because every script in my application has its own lua_State. The above code works fine when I call script::get_property from Script1.lua.

Since all of my scripts have access to other scripts in their contexts when I try to do this in other scripts like Script2.lua or Script3.lua or others:

print(type(script1:get_property()))

It won't print data type here properly and it'll return a number instead, which is a wrong result and the reason is script1:get_property() is returning a value that is only understood by script1 and not in other scripts.

I understand values that have been registered in script1 are only registered into that script's stack and registry table particularly and no one else, but my question is, is there any way to transfer these values between different Lua states?

Thanks.

\$\endgroup\$
2
  • \$\begingroup\$ What we're really interested in is why you need to transfer variables between states? Its far more likely that your overall architecture is flawed. (And by the sounds of it you're using lua too far into your stack) \$\endgroup\$
    – Matt D
    Commented Sep 25, 2013 at 1:55
  • \$\begingroup\$ @MattD Each script has a property which it's accessible by others. This makes scripts to be able to share data at run-time and the reason that I used luabind::object is for its generic behavior. The whole thing that I've presented here is just an example of what I'm trying to express because the actual project is more complex than this. And, I don't think there would be any flaw in here. \$\endgroup\$
    – MahanGM
    Commented Sep 25, 2013 at 10:10

1 Answer 1

1
+50
\$\begingroup\$

Since you can't guarantee anything about the type of the argument you're passing between the states, essentially what you're looking for is to serialize / de-serialize the object. Fortunately Programming in Lua covers this: Chapter 12 - Data Files and Persistence. Essentially you are converting your Lua object from one state into a stream of bytes, passing it to your C++ layer as a stream of bytes, then passing it to the second state still as a stream of bytes, and then de-serialising it into table/object form again on the other side.

That's the only type-safe, generic way to transfer data of arbitrary types between lua_States, although if you have constraints on the types of data then you might be able to make assumptions about what sort of data you need to serialize.

\$\endgroup\$
8
  • \$\begingroup\$ I know I can cast data returned by argument to the relevant object in C++ and then fetch it to the property which it is what I've been doing a while ago, but the problem here is I don't want to determine what type of data is traveling between so I need some generic solution for this. That's the only point. \$\endgroup\$
    – MahanGM
    Commented Sep 25, 2013 at 17:33
  • \$\begingroup\$ That was my point. Chapter 12 describes essentially a generic way of serialising any data, regardless of type. You don't need to know what data is being transferred, the C++ layer only ever considers it to be a byte array, and the Lua layers on either side are the things which convert the table/number/string/whatever into a byte array and back. You'll note the code in 12.1.1 recursively calls serialize if you're serializing a table, or just serializes the value directly if it's a number or a string. You can call serialize(o) on any object, regardless of its type, and it'll get serialized. \$\endgroup\$
    – MrCranky
    Commented Sep 28, 2013 at 9:01
  • \$\begingroup\$ Well as far as I know my problem is with the way that luabind::object is traveling. Besides, I don't want to serialize my data in Lua directly rather I want to do it in C++ which it'll bring the need for casting. Currently the data provided by this->property_field is wrong because the actual value is in the first script's stack and it's not going to transfer itself to other scripts' stacks when I try to get it from them. \$\endgroup\$
    – MahanGM
    Commented Sep 28, 2013 at 16:55
  • \$\begingroup\$ I think you're misunderstanding what creating a new luabind::object is doing. Note in get_property you're ignoring the lua_State being passed in, but returning a luabind::object. You're assuming the object is atomic, and that luabind will reach across to the first lua_State and ask it what the value actually is. But that would be super expensive, because it would have to copy the object into C++ memory, then create a new copy of it in the second Lua state, then tell the calling Lua function in the second state "here's the object set for that property." \$\endgroup\$
    – MrCranky
    Commented Sep 30, 2013 at 14:23
  • \$\begingroup\$ My bet is that internally, a luabind::object is just a pointer or an index, saying "Object 50 in State X". Any other lua script operating in the context of state X can simply say "Ah, object 50!" and go look it up, no need to copy anything. But in state Y, object 50 might be something completely different, a string, or whatever. But if it's trying to be fast, then it'll assume that the luabind::object exists in the same Lua state that it does. So I'm thinking that Matt D is right - you're maybe trying to use luabind in a way it can't be used, between multiple states. \$\endgroup\$
    – MrCranky
    Commented Sep 30, 2013 at 14:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .