Skip to main content
gamedev.net
🔒 Locked

Embedding Python/LUA

Started by Silvo Apr 18, 2006 at 11:07 PM 27 replies 6.1k views
Original Post
Silvo
Silvo
OK, ive looked everywhere, or at least, in most places, on a way to embed python in c++. After trying this, i tried LUA, no such luck. All I want to do is enable my C++ application to execute python/LUA scripts. So, I write a function or similar in python/LUA, store that in a seperate file, and in my C++ program, call that file/function, and it runs it with the python/LUA interpreter. This seems to be somethig that many people could benefit from, do you know a way I can do this, or a source that will tell me?
hplus0603
hplus0603
Did you try reading the manual?

Both Python and Lua come with manuals, that document how to do exactly that.

There are several libraries that provide additional features on top of the bindings provided by the libraries, too; SWIG is one; boost::python is another (specific to Python); don't know if there's a boost::lua yet.

Embedding LUA in a C++ program is literally a matter of a few lines of code; it's very simple. The manual has good examples.
enum Bool { True, False, FileNotFound };
Silvo
Silvo
Hmm, decided to go with LUA (had a bit of experience with making a WoW AddOn). After looking through their manual, I can't find any decent examples on how to embed LUA with C++ in it. It has loads of info on syntax, but no info on embedding it.
Silvo
Silvo
It seems that no tutorials work with me...
benstr
benstr
Try this. There's a section about the C-API in there. And you can also check luabind out.

- Benny -
-Benny-
Programmer16
Programmer16
If you're using a newer version of LUA then some of the names have changed and thus old tutorials are kind of rendered moot.

Here's an example I whipped up using the newest version:
lua_State* g_pState = 0;int main(){	g_pState = lua_open();	luaL_openlibs(g_pState);	lua_register(g_pState, NameString, FunctionPointer);	luaL_dofile(g_pState, FileNameString);	system("pause");	lua_close(g_pState);	return 0;}


Everything else is the say as in old the old tutorials (at least as far as I have seen.)

HTH!
John Schultz
John Schultz
If you are open to another lua-like scripting language with (closer to) C++ style syntax, and have Visual Studio 2005 (VS8), you can have Squirrel (scripting language) with SqPlus (binding system) compiled and running in about 5 minutes (gcc is also supported with basic makefiles).

Hello World:
int main(int argc,char * argv[]) {  SquirrelVM::Init();  SquirrelObject helloWorld = SquirrelVM::CompileBuffer(_T("print(\"Hello World\");"));  SquirrelVM::RunScript(helloWorld);  SquirrelVM::Shutdown();  return 0;} // main


Binding a class and interacting between Cpp and script, optional remote debugger usage (forum reformated the listing; see the .zip source file for original formatting):

#ifdef USE_REMOTE_DEBUGGERvoid printSQDBGError(HSQUIRRELVM v) {  const SQChar *err;  sq_getlasterror(v);  if(SQ_SUCCEEDED(sq_getstring(v,-1,&err))) {    scprintf(_T("SQDBG error : %s"),err);  }else {    scprintf(_T("SQDBG error"),err);  } // if  sq_poptop(v);} // printSQDBGError#endifstatic void printFunc(HSQUIRRELVM v,const SQChar * s,...) {  static SQChar temp[2048];  va_list vl;  va_start(vl,s);  scvsprintf( temp,s,vl);  SCPUTS(temp);  va_end(vl);} // printFunc// This class will be instantiated and used in script.class MyClass {public:  int classVal;  // See examples in testSqPlus2.cpp for passing arguments to the constructor (including variable arguments).  MyClass() : classVal(123) {}  bool process(int iVal,const SQChar * sVal) {    scprintf(_T("classVal: %d, iVal: %d, sVal %s\n"),classVal,iVal,sVal);    classVal += iVal;    return iVal > 1;  } // process};int main(int argc,char * argv[]) {  SquirrelVM::Init();  // This example shows how to redirect print output to your own custom  // print function (the default handler prints to stdout).  sq_setprintfunc(SquirrelVM::GetVMPtr(),printFunc);#ifdef USE_REMOTE_DEBUGGER  HSQREMOTEDBG rdbg = sq_rdbg_init(SquirrelVM::GetVMPtr(),1234,SQTrue);  if(rdbg) {    // Enable debug info generation (for the compiler).    sq_enabledebuginfo(SquirrelVM::GetVMPtr(),SQTrue);    scprintf(_T("Waiting for SQDBG connection..."));    // Suspends the app until the debugger client connects.    if(SQ_SUCCEEDED(sq_rdbg_waitforconnections(rdbg))) {      printf("SQDBG: connected.\n");    } // if  } else {    printSQDBGError(SquirrelVM::GetVMPtr());    return 0;  } // if#endif  // See examples in testSqPlus2.cpp for script read-only vars, constants,  // enums, static/global functions, variable arguments, constructor arguments,   // passing/returning classes/structs by value or by address, etc.  SQClassDef<MyClass>(_T("MyClass")).    func(&MyClass::process,_T("process")).    var(&MyClass::classVal,_T("classVal"));  SquirrelObject helloSqPlus = SquirrelVM::CompileBuffer(_T("    local myClass = MyClass();                           \n    local rVal = myClass.process(1,\"MyClass1\");        \n    print(\"Returned: \"+(rVal ? \"true\" : \"false\")); \n    rVal = myClass.process(2,\"MyClass2\");              \n    print(\"Returned: \"+(rVal ? \"true\" : \"false\")); \n    print(\"classVal: \"+myClass.classVal);              \n  "));  try {    SquirrelVM::RunScript(helloSqPlus);  } catch (SquirrelError & e) {    scprintf(_T("Error: %s, %s\n"),e.desc,_T("Squirrel::helloSqPlus"));  } // catch#ifdef USE_REMOTE_DEBUGGER  if (rdbg) {    sq_rdbg_shutdown(rdbg);  } // if#endif  SquirrelVM::Shutdown();  return 0;} // main


The remote debugger is portable and uses the Eclipse environment (supports syntax highlighting, etc.).

You may also want to check out Angel Script (a statically-typed scripting language (lua and Squirrel are dynamically typed)).
xiuhcoatl
xiuhcoatl
If you really have your heart set on LUA/Python and free forms of data are not helping, I would try "Game Scripting Mastery". Its a *very* good book on scripting extensions and embedding. It will deviate about half way through where you design your own system, both IL and HL - but the first part of it has about the best demonstration for extending/embedding for TCL, Python, and LUA.

You should be able to get a used copy for a reasonable price.


I hope that helps.
"C and C++ programmers seem to think that the shortest distance between two points is the great circle route on a spherical distortion of Euclidean space."Stephen Dewhurst
Silvo
Silvo
Thanks everyone for your help.

Barakus,

I tried that tutorial, doesnt seem to work with LUA 5

Benstr,

Thanks for the links! Programming in LUA seems good, but complex. LUAPlus doesnt provide enough information on embedding it, so i think I'll give it a miss.

Programmer16,

Yes, I think the problem is that LUA no longer supports those functions, so thanks for the new code. But I think you've used variables instead of actual arguments. What do these variables represent, do you recon you could walk me through it?

John Schultz,

Thanks, but I'm not using VC++, I'm using Code::Blocks (with Dev-cpp's compiler). I did look at squirrel beforehand, but decided against it (but Ive forgotten why, so Im looking at it again. SqPlus looks good too (just found out that you made it) Ill look into that.

Xiuhcoatl,

That would sort of be a last resort. Im in the middle of SAMS Teach Yourself C++ in 21 days, and am waiting for Code Complete, so Im kind of short on book reading time. Im positive that I can get something to work, but such a purchase may be nessessary in the near future. Thanks for the pointer!
John Schultz
John Schultz
Quote:
Original post by Silvo
Thanks, but I'm not using VC++, I'm using Code::Blocks (with Dev-cpp's compiler). I did look at squirrel beforehand, but decided against it (but Ive forgotten why, so Im looking at it again. SqPlus looks good too (just found out that you made it) Ill look into that.


It looks like Dev-cpp can use gcc; Squrriel with SqPlus should work OK (tested).
Programmer16
Programmer16
Quote:
Original post by Silvo
Programmer16,

Yes, I think the problem is that LUA no longer supports those functions, so thanks for the new code. But I think you've used variables instead of actual arguments. What do these variables represent, do you recon you could walk me through it?


lua_register(g_pState, FunctionName, FunctionPointer);// Exampleint sfSpeak(lua_State* pState){    // This returns the number of arguments that the user supplied.    lua_gettop(pState);    std::cout<<lua_tostring(pState, 1)<<": "<<lua_tostring(pState, 2)<<std::endl;    return 0;}lua_register(g_pState, "UserSpeak", sfSpeak);// The FunctionName argument is the function name that will be used// inside of the script./*Talking.lua-----------UserSpeak("Donny", "This is a user speaking.");UserSpeak("Silvo", "This is another user speaking.");*/// lua_dofile just a pointer to your virtual machine and a script filename.


I just started learning myself, so some of what I may be doing is wrong. For instance, in sfSpeak you should check to make sure that lua_gettop() returns 2 (meaning that the function was called with 2 strings.)

HTH!

Edit: Check out the tutorials at tonyandpaige.com. They're the ones that I used to get started (they use the old version, but other than the luaL_XXX functions that were in my first snippet, everything else seems to be the same.

Heres a link: TonyAndPaige.com
Silvo
Silvo
Programmer16,

I wish I understood what it all means... I used the tutorial you linked to, replacing your function names with theirs, but im getting some linker errors.

"
mian.cpp:13: error: luaL_newstate' undeclared (first use this function)
mian.cpp:13: error: (Each undeclared identifier is reported only once for each function it appears in.)
mian.cpp:17: error:
luaL_dofile' undeclared (first use this function)
"

yes, i spelt 'main' wrong... oh well. Also, it cant find luaxlib.h, but it's there

John,

Can you direct me to a hello world tutorial for squirrel and SqPlus?
John Schultz
John Schultz
Quote:
Original post by Silvo
Can you direct me to a hello world tutorial for squirrel and SqPlus?


Download and unzip the SqSplus .zip.

1. Go to the top level directory to where you unzipped the files and type: make sq32 (or examine the Makefiles and recreate in your IDE).
2. Go to the minimalSqPlus directory and type: make
3. type: ./minimalSqPlus to run.
4. See minimalSqPlus.cpp for more info.
5. See testSqPlus2/testSqPlus2.cpp for examples of just about everything you might need for binding. See the Squirrel forum for more info (other gcc/non-VC users are helpful).

Squirrel Docs
Squirrel Forum
Silvo
Silvo
Thanks for the assisstance.

Just to let you know, im using Windoze, so the make stuff and ./blah dont work. I tried looking at the Makefiles (not sure what these do), and saw some stuff under sq32, so I added them as link libraries. The problem is that these dont exist, so after removing them from the list, it cant find any of the functions (copied the source from minimalSqPlus.cpp). Im assumming i need some libraries, but i cant see them. (looked in the lib folder).
NickGravelyn
NickGravelyn
Quote:
Original post by Programmer16
If you're using a newer version of LUA then some of the names have changed and thus old tutorials are kind of rendered moot.

Here's an example I whipped up using the newest version:
*** Source Snippet Removed ***

Everything else is the say as in old the old tutorials (at least as far as I have seen.)

HTH!


Is that using C++ or C? On my Mac I can get Lua to work fine with a C app compiled with gcc, but when I use a C++ app compiled with g++ I get an error that lua_dofile is undeclared. I'm using extern "C" {} for the lua headers and I'm positive I'm linking to the libraries properly (again, I can get it to work using straight C). Any ideas how to get it to work in C++? Here's my full code:
#include <stdio.h>#include <stdlib.h>extern "C" {#include <lua.h>#include <lualib.h>}lua_State *L;int main(int argc, char * const argv[]){   L = lua_open();   luaopen_base(L);   lua_dofile(L, "SimAI.lua");   lua_close(L);   return 0;}
NickGravelyn
NickGravelyn
Figured out the problem. I do need to include but when it installed it, it created it as lauxlib (the u and a are backwards). After renaming that and using luaL_loadfile() it works just fine.
John Schultz
John Schultz
Quote:
Original post by Silvo
Thanks for the assisstance.

Just to let you know, im using Windoze, so the make stuff and ./blah dont work. I tried looking at the Makefiles (not sure what these do), and saw some stuff under sq32, so I added them as link libraries. The problem is that these dont exist, so after removing them from the list, it cant find any of the functions (copied the source from minimalSqPlus.cpp). Im assumming i need some libraries, but i cant see them. (looked in the lib folder).


Silvo, is there some reason you can't use the free version of Visual Studio 2005 (C++ Express)?

It sounds like the trouble you are having with embedding a scripting language is due to the compiler/IDE/environment you are using as opposed to the scripting language and binding tools.

If you download the free VS2005 for C++, you will be able to open the Squirrel/SqPlus solution (.sln file) and immediately compile, link and run with no problems. If you need to use some other IDE/compiler, you can study the VS2005 solution items and recreate the build/make files from scratch.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.