Add test for extending exported classes in Lua.
[luabind.git] / src / function.cpp
blob37338f9dab149deb0d53b2f7130016212a6b06c3
1 // Copyright Daniel Wallin 2008. Use, modification and distribution is
2 // subject to the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 #define LUABIND_BUILDING
7 #include <luabind/make_function.hpp>
9 namespace luabind { namespace detail {
11 namespace
14 int function_destroy(lua_State* L)
16 function_object* fn = *(function_object**)lua_touserdata(L, 1);
17 delete fn;
18 return 0;
21 void push_function_metatable(lua_State* L)
23 lua_pushstring(L, "luabind.function");
24 lua_rawget(L, LUA_REGISTRYINDEX);
26 if (lua_istable(L, -1))
27 return;
29 lua_pop(L, 1);
31 lua_newtable(L);
33 lua_pushstring(L, "__gc");
34 lua_pushcclosure(L, &function_destroy, 0);
35 lua_rawset(L, -3);
37 lua_pushstring(L, "luabind.function");
38 lua_pushvalue(L, -2);
39 lua_rawset(L, LUA_REGISTRYINDEX);
42 // A pointer to this is used as a tag value to identify functions exported
43 // by luabind.
44 int function_tag = 0;
46 } // namespace unnamed
48 LUABIND_API bool is_luabind_function(lua_State* L, int index)
50 if (!lua_getupvalue(L, index, 2))
51 return false;
52 bool result = lua_touserdata(L, -1) == &function_tag;
53 lua_pop(L, 1);
54 return result;
57 namespace
60 inline bool is_luabind_function(object const& obj)
62 obj.push(obj.interpreter());
63 bool result = detail::is_luabind_function(obj.interpreter(), -1);
64 lua_pop(obj.interpreter(), 1);
65 return result;
68 } // namespace unnamed
70 LUABIND_API void add_overload(
71 object const& context, char const* name, object const& fn)
73 function_object* f = *touserdata<function_object*>(getupvalue(fn, 1));
74 f->name = name;
76 if (object overloads = context[name])
78 if (is_luabind_function(overloads) && is_luabind_function(fn))
80 f->next = *touserdata<function_object*>(getupvalue(overloads, 1));
81 f->keepalive = overloads;
85 context[name] = fn;
88 LUABIND_API object make_function_aux(lua_State* L, int arity, function_object* impl)
90 void* storage = lua_newuserdata(L, sizeof(function_object*));
91 push_function_metatable(L);
92 *(function_object**)storage = impl;
93 lua_setmetatable(L, -2);
95 lua_pushlightuserdata(L, &function_tag);
96 lua_pushcclosure(L, impl->entry, 2);
97 stack_pop pop(L, 1);
99 return object(from_stack(L, -1));
102 void invoke_context::format_error(
103 lua_State* L, function_object const* overloads) const
105 char const* function_name =
106 overloads->name.empty() ? "<unknown>" : overloads->name.c_str();
108 if (candidate_index == 0)
110 lua_pushstring(L, "No matching overload found, candidates:\n");
111 int count = 0;
112 for (function_object const* f = overloads; f != 0; f = f->next)
114 if (count != 0)
115 lua_pushstring(L, "\n");
116 f->format_signature(L, function_name);
117 ++count;
119 lua_concat(L, count * 2);
121 else
123 // Ambiguous
124 lua_pushstring(L, "Ambiguous, candidates:\n");
125 for (int i = 0; i < candidate_index; ++i)
127 if (i != 0)
128 lua_pushstring(L, "\n");
129 candidates[i]->format_signature(L, function_name);
131 lua_concat(L, candidate_index * 2);
135 }} // namespace luabind::detail