I'm fairly sure Lua can do everything you need relatively simply. I use Lua and C++ in my game. I looked at various wrappers like LuaBind, or using a generator like Swig, but I decided I didn't want any of that stuff and I wrote my own wrapper which I ended up making open source in case other people found it useful.
Using my little library you can do stuff like this in C++:
// Wrap a C++ function
static int Widget_AddChild(lua_State* L)
{
// Typesafe way to extract userdata from Lua
Widget* parent = luaW_check<Widget>(L, 1);
Widget* child = luaW_check<Widget>(L, 2);
lua_pushboolean(L, parent->AddChild(child));
}
static luaL_reg Widget_Metatable[] =
{
// Register the function you wrote above
{ "AddChild", Widget_AddChild },
// Widgets also have some getter and setter functions,
// Using these templates you can automatically generate
// wrapper functions for them
{ "GetStyle", luaU_get<Widget, Style, &Widget::GetStyle> },
{ "SetStyle", luaU_set<Widget, Style, &Widget::SetStyle> },
{ "Style", luaU_getset<Widget, Style, &Widget::GetStyle, &Widget::SetStyle> },
{ NULL, NULL }
};
int luaopen_Widget(lua_State* L)
{
luaW_register<Widget>(L, "Widget", NULL, Widget_Metatable);
return 1;
}
In lua you could now do something like this:
local w = Widget.new()
w.foo = 10 -- Foo is stored on w, it's not accessible to other instances
-- You can also add values accessible to all Widgets
function Widget.metatable:newfunction()
print(self:GetWidth())
end
w:newfunction()
With all that, you can fairly easily call C++ function from Lua (and vice versa, but I didn't illustrate that here). Once you know how to interact with the Lua API, writing a function to 'safely' call (i.e. call a function only if it exists) a Lua function should be easy as well.
Edit:
If you want to check for the existence of a function before calling it, like I said, just check that the value is a function before calling it.
lua_getglobal(L, "myFunc"); // You can get your function from anywhere, this is just for example
if (lua_isfunction(L, -1)) // Check the top of the stack, make sure it's a function
{
lua_call(L, 0, 0);
}