Skip to main content
gamedev.net
🔒 Locked

Lua function as C++ parameter?

Started by Tenac Jul 12, 2008 at 1:17 AM 5 replies 2.7k views
Original Post
Tenac
Tenac
I'm using lua and luabind to link my C++ classes/methods to lua mainly for GUI creation similar to world of warcraft's but I ran into one think I can't figure out, how can I have a lua function as a parameter in a C++ method. An example in lua would be: local Frame = CreateFrame("Frame", nil); Frame:SetScript("OnMouseDown", function() print("print me!"); end); What would SetScript look like in C++? Currently I have it as SetScript(string foo1, const char* foo2) and I put the second parameter in quotes in lua so I could do luaL_dostring but it's time for me to fix this. Would anyone know what I could do to make this possible?
Tenac
Tenac
Is this even possible or if not, is there some sort of alternative? Did WoW modify lua to be able to do this?
hh10k
hh10k
Lua's normal C API lets you take a function (or anything else) as a parameter, but I'm not familiar with luabind. Sorry I can't help more :)
ddn3
ddn3
A simple way would be have some intermediary in Lua to hold these functions in a table, which u can index with a simply interger key from C++ script. So internally to C++ the lua function is a handle into this table. And when it comes to disaptch the function u go through a catch all Lua function which interns accesses the functor table to dispatch the call. Not most efficent since ur doing somewhat more work but its ezy.

-ddn
rudeness
rudeness
Hello.

luaL_ref does what ddn3 suggests.

Recently, I needed to attach arbitrary Lua data to Shape objects for collision response purposes. Here's some code:

(Table love.refs holds the references.)

// First param is the object in question.// Second param is arbitrary data.int _CircleShape_setData(lua_State * L){	if(lua_gettop(L) != 2) return luaL_error(L, "Incorrect number of parameters.");	pCircleShape p = mod_to_circleshape(L, 1);	lua_getglobal(L, "love");	lua_getfield(L, -1, "refs");	lua_pushvalue(L, -3); // Copies second param to the top.	int ref = luaL_ref(L, -2);	p->setData(ref);	return 0;}int _CircleShape_getData(lua_State * L){	if(lua_gettop(L) != 1) return luaL_error(L, "Incorrect number of parameters.");	pCircleShape p = mod_to_circleshape(L, 1);	int ref = p->getData();	lua_getglobal(L, "love");	lua_getfield(L, -1, "refs");	lua_rawgeti(L, -1, ref);	return 1;}


This way you can "store" Lua data (including functions) in C++ using a single int.
bobofjoe
bobofjoe
Using luabind, you can accept functions to your C++ functions in the form of luabind::object.

In order to invoke that function, you will have to call luabind::call_function( functionObject, args ... );
or
functionObject( args ... );

Example!
//C++luabind::object functionObject;void setObject(luabind::object func){	functionObject = func;}void invoke(){	if (luabind::type(functionObject) == LUA_TFUNCTION)	{		luabind::call_function<void>(functionObject);		//This syntax also works:		//functionObject();	} else {		//You did it wrong.		throw std::runtime_exception("Lua Object not a function.");	}}void bindToLua(lua_State * state){	luabind::open(state);	luabind::module(state)	[		luabind::def("setObject", setObject),		luabind::def("invoke", invoke)	];}//Lua (Assuming you have bound the correct stuff correctly, of course)function Foo()	print("I see what you did thar");endsetObject(Foo);invoke();


This should print "I see what you did thar" to the console. This is pretty much as type safe as it is going to get, since lua dosn't really have a strict typing system.

Note that you will have to
#include <luabind/object.hpp>

to get this to work, though.
[size=1]Visit my website, rawrrawr.com
Tenac
Tenac
bobofjoe, your the greatest, that worked perfectly how I wanted it to!

Thanks everyone for the help and I gave all of you good ratings.

Topic Locked

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

Sign in to reply to this topic.