LUA Is possible to expose my C++ objects to LUA scripting ?

dumbo2007

Crazy about real time sims
Joined
Nov 29, 2009
Messages
675
Reaction score
0
Points
0
Location
India
Hi,

I was wondering if its possible to allow objects I develop in C++ such as the rover or anything else more complex to expose to LUA scripting, thus adding to the already available set of functions in LUA. Maybe expose some specific functions only that let the speed, heading etc be set. Perhaps the LUA script engine can callback these functions after properly marshaling the arguments ?

I understand that LUA can be used to set the speed, mass, orientation etc of VESSEL objects, but can its existing set of functions be added to, when I design VESSEL class derived objects that add their own functions ?

Thanks.
 
Last edited:

escapetomsfate

OBSP Developer
Addon Developer
Joined
Jun 21, 2008
Messages
282
Reaction score
0
Points
0
Location
GB
Hi,

I was wondering if its possible to allow objects I develop in C++ such as the rover or anything else more complex to expose to LUA scripting, thus adding to the already available set of functions in LUA. Maybe expose some specific functions only that let the speed, heading etc be set. Perhaps the LUA script engine can callback these functions after properly marshaling the arguments ?

I understand that LUA can be used to set the speed, mass, orientation etc of VESSEL objects, but can its existing set of functions be added to, when I design VESSEL class derived objects that add their own functions ?

Thanks.

Do you mean defining new Lua functions for your vessel?

For a single vessel it's pretty easy:

In clbkGeneric, look for the VMSG_LUAINSTANCE message (taken from Orbiter Help docs) -
Code:
int MyVessel::clbkGeneric (int msgid, int prm, void *context)
{
  switch (msgid) {
  case VMSG_LUAINSTANCE:
    return Lua_InitInstance (context);
  }
  return 0;
}

int MyVessel::Lua_InitInstance (void *context)
{
  lua_State *L = (lua_State*)context;
  luaL_getmetatable (L, "VESSEL.MYVESSEL");
  if (lua_isnil(L,-1)) { // class not yet registered
    lua_pop(L,1);
    static const struct luaL_reg myvesselLib[] = {
      {"gear_up", myvessel_gear_up},
      {"gear_dn", myvessel_gear_dn},
      {NULL, NULL}
    };
    luaL_newmetatable (L, "MYVESSEL.vtable");
    luaL_openlib (L, "MYVESSEL.method", myvesselLib, 0);
    luaL_newmetatable (L, "MYVESSEL.base");
    lua_pushstring (L, "__index");
    luaL_getmetatable (L, "VESSEL.vtable");
    lua_settable (L, -3);
    lua_setmetatable (L, -2);
    lua_pushstring (L, "__index");
    lua_pushvalue (L, -2);
    lua_settable (L, -4);
    lua_pop (L, 1);
  }
  lua_setmetatable (L, -2);
  return 0;
}

That means you can do this in a script:
Code:
v=vessel.get_interface('MyVessel')
v:gear_up()
v:gear_dn()

It's easier to use lua_register to define global lua functions if you're just using it to test stuff out, but the table way is neater.
 

dumbo2007

Crazy about real time sims
Joined
Nov 29, 2009
Messages
675
Reaction score
0
Points
0
Location
India
Code:
  static const struct luaL_reg myvesselLib[] = {
      {"gear_up", myvessel_gear_up},
      {"gear_dn", myvessel_gear_dn},
      {NULL, NULL}

Yes, that is exactly what I wanted. To make my functions callable from LUA. I thought that only the standard VESSEL functions could be called, but I see that I can add my own functions too just as in normal C++.

By the way, the lua_register can be used in a plugin ? To tie some function in my plugin to LUA so it can be directly called from a script. I was also wondering which PDF has the LUA documentation.
 
Last edited:

escapetomsfate

OBSP Developer
Addon Developer
Joined
Jun 21, 2008
Messages
282
Reaction score
0
Points
0
Location
GB
By the way, the lua_register can be used in a plugin ? To tie some function in my plugin to LUA so it can be directly called from a script. I was also wondering which PDF has the LUA documentation.

Plugins are harder... You can make Orbiter create a new interpreter (with Orbiter lua functions already loaded) like this:

Code:
INTERPRETERHANDLE LuaInterpreter = oapiCreateInterpreter();
lua_State* L = oapiGetLua(LuaInterpreter);
lua_register(L, "MyFunction", MyFunction);

However - this isn't the same interpreter instance that Orbiter uses to read scripts or commands in LuaMFD. It's just an interpreter you can use for reading scripts that are separate to the main scenario ones, or perhaps a ship's command console.

As far as I can tell there's no "proper" way in the API to define global Lua functions for any interpreter instance. However, I found a cheat while working on OBSP's Lua script feature:

Make a class extended from VESSEL3 in your plugin module, and in its clbkGeneric function register all the global lua functions you need when you get the VMSG_LUAINSTACE message, like I showed you before. Register the vessel class in the plugin as if it's a normal vessel module. Then, make a config file for the vessel, and point its MODULE parameter to Plugin\YourPlugin.

Now you can run your lua functions. Before you do so, you need to spawn the vessel you created a config/code for, and send it the VMSG_LUAINSTANCE message by calling this lua function: vessel.get_interface('MyLuaVessel').

That way works a charm for OBSP. Only problem is, you constantly have to have an invisible LuaVessel in the scenario for scripts to run properly. The API should have callback functions that allow plugins to register new Lua functions each time a new interpreter is created.

The documentation for Lua scripts isn't in any of the OrbiterSDK pdf - it's all in the compiled HTML Help file (just click the "Help" button at the bottom right of the Launchpad).
 

dumbo2007

Crazy about real time sims
Joined
Nov 29, 2009
Messages
675
Reaction score
0
Points
0
Location
India
Then, make a config file for the vessel, and point its MODULE parameter to Plugin\YourPlugin.

Interesting ! didnt know that the latter part could be done :), but yeah I guess a VESSEL module and a general plugin module is basically the same.
 

JMW

Aspiring Addon Developer
Joined
Aug 5, 2008
Messages
611
Reaction score
52
Points
43
Location
Happy Wherever
Is it possible to run scripts from a module, entering information into the script program - say "hdg" value in "aap.hdg", from a .dll computed value, for example 90 deg?

and you know what the next question will be ......:lol:
 

escapetomsfate

OBSP Developer
Addon Developer
Joined
Jun 21, 2008
Messages
282
Reaction score
0
Points
0
Location
GB
Is it possible to run scripts from a module, entering information into the script program - say "hdg" value in "aap.hdg", from a .dll computed value, for example 90 deg?

and you know what the next question will be ......:lol:

So, you want to start a script from a plugin/vessel module, and change the value of some variables?

First you need to create a new script interpreter and get its lua_State...

Code:
INTERPRETERHANDLE LuaInterpreter = oapiCreateInterpreter();
lua_State* L = oapiGetLua(LuaInterpreter);

Then run the script:

Code:
luaL_dofile(L,"YourScript.lua");

I'm not actually sure if this path is relative to Orbiter's root directory or the Script folder. Try "Script/YourScript" if the above doesn't work.

Then to change a variable's value:

Code:
lua_pushnumber(L, 90);
lua_setglobal(L, "hdg");

This works fine for global variables. I'm not sure exactly how you'd change values in a table (such as aap.hdg) but possibly something like this:

Code:
lua_getglobal(L, "aap");
lua_pushnumber(L, 90);
lua_setfield(L, -2, "hdg");

-2 should give the right index of the table if it's second on the stack like that, but I'm not too sure. Let me know if that works :)
 
Last edited:

JMW

Aspiring Addon Developer
Joined
Aug 5, 2008
Messages
611
Reaction score
52
Points
43
Location
Happy Wherever
Thanks escapetomsfate, but I get these errors:
PHP:
1>Copy (9) of Copy of J-F-35B_Stepping_Pad_8.1_THE_ONE.obj : error LNK2019: unresolved external symbol _lua_setfield referenced in function "public: virtual void __thiscall ShuttlePB::clbkPostStep(double,double,double)" (?clbkPostStep@ShuttlePB@@UAEXNNN@Z)
1>Copy (9) of Copy of J-F-35B_Stepping_Pad_8.1_THE_ONE.obj : error LNK2019: unresolved external symbol _lua_pushnumber referenced in function "public: virtual void __thiscall ShuttlePB::clbkPostStep(double,double,double)" (?clbkPostStep@ShuttlePB@@UAEXNNN@Z)
1>Copy (9) of Copy of J-F-35B_Stepping_Pad_8.1_THE_ONE.obj : error LNK2019: unresolved external symbol _lua_pcall referenced in function "public: virtual void __thiscall ShuttlePB::clbkPostStep(double,double,double)" (?clbkPostStep@ShuttlePB@@UAEXNNN@Z)
1>Copy (9) of Copy of J-F-35B_Stepping_Pad_8.1_THE_ONE.obj : error LNK2019: unresolved external symbol _luaL_loadfile referenced in function "public: virtual void __thiscall ShuttlePB::clbkPostStep(double,double,double)" (?clbkPostStep@ShuttlePB@@UAEXNNN@Z)
1>C:\Orbiter 2010\Modules\JMW\J-F-35B.dll : fatal error LNK1120: 4 unresolved externals
1>Build log was saved at "file://c:\Documents and Settings\John\My Documents\Visual Studio 2008\Projects\Concorde\2010\Release\BuildLog.htm"
 

orb

New member
News Reporter
Joined
Oct 30, 2009
Messages
14,020
Reaction score
4
Points
0
There are lua5.1.lib and lua51.lib in "Orbitersdk/lib/lua". Did you include lua5.1.lib as additional (Linker) dependency?
 

JMW

Aspiring Addon Developer
Joined
Aug 5, 2008
Messages
611
Reaction score
52
Points
43
Location
Happy Wherever
Nope - I hadn't.

Thanks Orb, right on the nail (as usual)

Compiles now I've included lua5.1 , but when will lua51 be needed?

Regards...:cheers:
 

orb

New member
News Reporter
Joined
Oct 30, 2009
Messages
14,020
Reaction score
4
Points
0
Compiles now I've included lua5.1 , but when will lua51 be needed?
The lua51.lib includes exports from the lua51.dll. Since the DLL is only present in the "OrbiterSDK/lib/lua" directory, and in Orbiter's root directory is only lua5.1.dll, which only will be found and loaded by Orbiter, you will most likely never need to include the other one, unless future Orbiter releases change something with this.
 

JMW

Aspiring Addon Developer
Joined
Aug 5, 2008
Messages
611
Reaction score
52
Points
43
Location
Happy Wherever
So, you want to start a script from a plugin/vessel module, and change the value of some variables?

First you need to create a new script interpreter and get its lua_State...

Code:
INTERPRETERHANDLE LuaInterpreter = oapiCreateInterpreter();
lua_State* L = oapiGetLua(LuaInterpreter);

Then run the script:

Code:
luaL_dofile(L,"YourScript.lua");

I'm not actually sure if this path is relative to Orbiter's root directory or the Script folder. Try "Script/YourScript" if the above doesn't work.

Then to change a variable's value:

Code:
lua_pushnumber(L, 90);
lua_setglobal(L, "hdg");

This works fine for global variables. I'm not sure exactly how you'd change values in a table (such as aap.hdg) but possibly something like this:

Code:
lua_getglobal(L, "aap");
lua_pushnumber(L, 90);
lua_setfield(L, -2, "hdg");

-2 should give the right index of the table if it's second on the stack like that, but I'm not too sure. Let me know if that works :)

Managed to load the script ok -
Code:
int ShuttlePB::clbkGeneric (int msgid, int prm, void *context)
{
	switch (msgid) {
	case VMSG_LUAINTERPRETER:
		lua_State *L = (lua_State*)context;
		luaL_dofile (L, "Script\\35B\\aap.lua");
			
	}
	return 0;
}

Still struggling with changing value even of what I think is a global variable (alt & altid in dg/aap lua file) as per escapetomsfate's advice above.
Ant further help with this would be very welcome.:tiphat:
My current quest however is to dis-engage all autopilots (hdg/spd/alt) from the .dll
Is there a command that will do this that I can call from within the .dll, and if so how?
I've tried manipulating the values of the variables, I think without success - is there a way to check if the variables have been changed? - some sort of debug (gotta be simple for me to set up)
Or could someone "point" me in the right direction.
Obliged,
JMW
 
Last edited:
Top