function.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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)
  4. #define LUABIND_BUILDING
  5. #include <luabind/make_function.hpp>
  6. namespace luabind { namespace detail {
  7. namespace
  8. {
  9. int function_destroy(lua_State* L)
  10. {
  11. function_object* fn = *(function_object**)lua_touserdata(L, 1);
  12. delete fn;
  13. return 0;
  14. }
  15. void push_function_metatable(lua_State* L)
  16. {
  17. lua_pushstring(L, "luabind.function");
  18. lua_rawget(L, LUA_REGISTRYINDEX);
  19. if (lua_istable(L, -1))
  20. return;
  21. lua_pop(L, 1);
  22. lua_newtable(L);
  23. lua_pushstring(L, "__gc");
  24. lua_pushcclosure(L, &function_destroy, 0);
  25. lua_rawset(L, -3);
  26. lua_pushstring(L, "luabind.function");
  27. lua_pushvalue(L, -2);
  28. lua_rawset(L, LUA_REGISTRYINDEX);
  29. }
  30. // A pointer to this is used as a tag value to identify functions exported
  31. // by luabind.
  32. int function_tag = 0;
  33. } // namespace unnamed
  34. LUABIND_API bool is_luabind_function(lua_State* L, int index)
  35. {
  36. if (!lua_getupvalue(L, index, 2))
  37. return false;
  38. bool result = lua_touserdata(L, -1) == &function_tag;
  39. lua_pop(L, 1);
  40. return result;
  41. }
  42. namespace
  43. {
  44. inline bool is_luabind_function(object const& obj)
  45. {
  46. obj.push(obj.interpreter());
  47. bool result = detail::is_luabind_function(obj.interpreter(), -1);
  48. lua_pop(obj.interpreter(), 1);
  49. return result;
  50. }
  51. } // namespace unnamed
  52. LUABIND_API void add_overload(
  53. object const& context, char const* name, object const& fn)
  54. {
  55. function_object* f = *touserdata<function_object*>(getupvalue(fn, 1));
  56. f->name = name;
  57. if (object overloads = context[name])
  58. {
  59. if (is_luabind_function(overloads) && is_luabind_function(fn))
  60. {
  61. f->next = *touserdata<function_object*>(getupvalue(overloads, 1));
  62. f->keepalive = overloads;
  63. }
  64. }
  65. context[name] = fn;
  66. }
  67. LUABIND_API object make_function_aux(lua_State* L, function_object* impl)
  68. {
  69. void* storage = lua_newuserdata(L, sizeof(function_object*));
  70. push_function_metatable(L);
  71. *(function_object**)storage = impl;
  72. lua_setmetatable(L, -2);
  73. lua_pushlightuserdata(L, &function_tag);
  74. lua_pushcclosure(L, impl->entry, 2);
  75. stack_pop pop(L, 1);
  76. return object(from_stack(L, -1));
  77. }
  78. void invoke_context::format_error(
  79. lua_State* L, function_object const* overloads) const
  80. {
  81. char const* function_name =
  82. overloads->name.empty() ? "<unknown>" : overloads->name.c_str();
  83. if (candidate_index == 0)
  84. {
  85. lua_pushstring(L, "No matching overload found, candidates:\n");
  86. int count = 0;
  87. for (function_object const* f = overloads; f != 0; f = f->next)
  88. {
  89. if (count != 0)
  90. lua_pushstring(L, "\n");
  91. f->format_signature(L, function_name);
  92. ++count;
  93. }
  94. lua_concat(L, count * 2);
  95. }
  96. else
  97. {
  98. // Ambiguous
  99. lua_pushstring(L, "Ambiguous, candidates:\n");
  100. for (int i = 0; i < candidate_index; ++i)
  101. {
  102. if (i != 0)
  103. lua_pushstring(L, "\n");
  104. candidates[i]->format_signature(L, function_name);
  105. }
  106. lua_concat(L, candidate_index * 2);
  107. }
  108. }
  109. }} // namespace luabind::detail