The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
lua_cpp_function.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2016 by Chris Beck <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
16 
17 #include "log.hpp"
18 
19 #include <sstream>
20 #include <string>
21 
22 #include "lua/lauxlib.h"
23 #include "lua/lua.h"
24 
25 static lg::log_domain log_scripting_lua("scripting/lua");
26 #define DBG_LUA LOG_STREAM(debug, log_scripting_lua)
27 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
28 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
29 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
30 
31 namespace lua_cpp {
32 
33 char const * cpp_function = "CPP_Function";
34 
35 static int intf_dispatcher ( lua_State* L )
36 {
37  //make a temporary copy, in case lua_remove(L,1) might cause lua to garbage collect and destroy it
38  lua_function f = * static_cast<lua_function *> (luaL_checkudata(L, 1, cpp_function));
39  // remove from the stack before executing, so that like all other callbacks, f finds only its intended arguments on the stack.
40  lua_remove(L,1);
41  int result = (f)(L);
42  return result;
43 }
44 
45 static int intf_cleanup ( lua_State* L )
46 {
47  lua_function * d = static_cast< lua_function *> (luaL_testudata(L, 1, cpp_function));
48  if (d == nullptr) {
49  ERR_LUA << "lua_cpp::intf_cleanup called on data of type: " << lua_typename( L, lua_type( L, 1 ) ) << std::endl;
50  ERR_LUA << "This may indicate a memory leak, please report at bugs.wesnoth.org" << std::endl;
51  lua_pushstring(L, "C++ function object garbage collection failure");
52  lua_error(L);
53  } else {
54  d->~lua_function();
55  }
56  return 0;
57 }
58 
59 static int intf_tostring( lua_State* L )
60 {
61  lua_function * d = static_cast< lua_function *> (luaL_checkudata(L, 1, cpp_function));
62  // d is not null, if it was null then checkudata raised a lua error and a longjump was executed.
63  std::stringstream result;
64  result << "c++ function: " << std::hex << d;
65  lua_pushstring(L, result.str().c_str());
66  return 1;
67 }
68 
70 {
71  luaL_newmetatable(L, cpp_function);
73  lua_setfield(L, -2, "__call");
75  lua_setfield(L, -2, "__gc");
77  lua_setfield(L, -2, "__tostring");
78  lua_pushvalue(L, -1); //make a copy of this table, set it to be its own __index table
79  lua_setfield(L, -2, "__index");
80 
81  lua_pop(L, 1);
82 }
83 
85 {
86  void * p = lua_newuserdata(L, sizeof(lua_function));
87  luaL_setmetatable(L, cpp_function);
88  new (p) lua_function(f);
89 }
90 
91 void set_functions( lua_State* L, const std::vector<lua_cpp::Reg>& functions)
92 {
94  for (const lua_cpp::Reg& l : functions) { /* fill the table with given functions */
95  if (l.name != nullptr) {
96  push_function(L, l.func);
97  lua_setfield(L, -2, l.name);
98  }
99  }
100 }
101 
103 {
104  lua_function * f = static_cast< lua_function *> (luaL_checkudata(L, lua_upvalueindex(1), cpp_function)); //assume the std::function is the first upvalue
105  return (*f)(L);
106 }
107 
108 void push_closure( lua_State* L, const lua_function & f, int nup)
109 {
110  push_function(L, f);
111  lua_insert(L, -(1+nup)); //move the function beneath the upvalues
113 }
114 
115 void set_functions( lua_State* L, const std::vector<lua_cpp::Reg>& functions, int nup )
116 {
118  luaL_checkstack(L, nup+1, "too many upvalues");
119  for (const lua_cpp::Reg& l : functions) { /* fill the table with given functions */
120  if (l.name == nullptr) {
121  continue;
122  }
123  int i;
124  for (i = 0; i < nup; ++i) /* copy upvalues to the top */
125  lua_pushvalue(L, -nup);
126  push_closure(L, l.func, nup); /* closure with those upvalues */
127  lua_setfield(L, -(nup + 2), l.name);
128  }
129  lua_pop(L, nup); /* remove upvalues */
130 }
131 
132 } // end namespace lua_cpp
std::function< int(lua_State *)> lua_function
LUALIB_API void * luaL_checkudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.cpp:307
#define lua_pushcfunction(L, f)
Definition: lua.h:328
LUA_API int lua_type(lua_State *L, int idx)
Definition: lapi.cpp:243
#define ERR_LUA
static int intf_closure_dispatcher(lua_State *L)
LUALIB_API void luaL_checkstack(lua_State *L, int space, const char *msg)
Definition: lauxlib.cpp:335
LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n)
Definition: lapi.cpp:549
#define d
LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
Definition: lauxlib.cpp:286
void push_function(lua_State *L, const lua_function &f)
Pushes a std::function wrapper object onto the stack.
LUA_API void * lua_newuserdata(lua_State *L, size_t size)
Definition: lapi.cpp:1169
#define lua_pop(L, n)
Definition: lua.h:322
GLdouble l
Definition: glew.h:6966
#define lua_upvalueindex(i)
Definition: lua.h:40
static int intf_cleanup(lua_State *L)
GLuint64EXT * result
Definition: glew.h:10727
void push_closure(lua_State *L, const lua_function &f, int nup)
Pushes a closure which retains a std::function object as its first up-value.
LUA_API void lua_remove(lua_State *L, int idx)
Definition: lapi.cpp:176
LUALIB_API void * luaL_testudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.cpp:292
GLfloat GLfloat p
Definition: glew.h:12766
LUALIB_API int luaL_newmetatable(lua_State *L, const char *tname)
Definition: lauxlib.cpp:274
#define luaL_checkversion(L)
Definition: lauxlib.h:29
size_t i
Definition: function.cpp:1057
char const * cpp_function
static int intf_dispatcher(lua_State *L)
LUA_API void lua_insert(lua_State *L, int idx)
Definition: lapi.cpp:187
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.cpp:229
LUA_API int lua_error(lua_State *L)
Definition: lapi.cpp:1099
Standard logging facilities (interface).
void register_metatable(lua_State *L)
static int intf_tostring(lua_State *L)
static lg::log_domain log_scripting_lua("scripting/lua")
LUA_API const char * lua_pushstring(lua_State *L, const char *s)
Definition: lapi.cpp:507
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:752
LUA_API const char * lua_typename(lua_State *L, int t)
Definition: lapi.cpp:249
GLclampf f
Definition: glew.h:3024
void set_functions(lua_State *L, const std::vector< lua_cpp::Reg > &functions)
Analogous to lua_setfuncs, it registers a collection of function wrapper objects into a table...