1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg 2 3 // Permission is hereby granted, free of charge, to any person obtaining a 4 // copy of this software and associated documentation files (the "Software"), 5 // to deal in the Software without restriction, including without limitation 6 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 // and/or sell copies of the Software, and to permit persons to whom the 8 // Software is furnished to do so, subject to the following conditions: 9 10 // The above copyright notice and this permission notice shall be included 11 // in all copies or substantial portions of the Software. 12 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 21 // OR OTHER DEALINGS IN THE SOFTWARE. 22 23 #define LUABIND_BUILDING 24 25 #include <luabind/lua_include.hpp> 26 27 #include <luabind/luabind.hpp> 28 29 namespace luabind { namespace detail 30 { 31 namespace 32 { 33 // expects two tables on the lua stack: 34 // 1: destination 35 // 2: source copy_member_table(lua_State * L)36 void copy_member_table(lua_State* L) 37 { 38 lua_pushnil(L); 39 40 while (lua_next(L, -2)) 41 { 42 lua_pushstring(L, "__init"); 43 if (lua_equal(L, -1, -3)) 44 { 45 lua_pop(L, 2); 46 continue; 47 } 48 else lua_pop(L, 1); // __init string 49 50 lua_pushstring(L, "__finalize"); 51 if (lua_equal(L, -1, -3)) 52 { 53 lua_pop(L, 2); 54 continue; 55 } 56 else lua_pop(L, 1); // __finalize string 57 58 lua_pushvalue(L, -2); // copy key 59 lua_insert(L, -2); 60 lua_settable(L, -5); 61 } 62 } 63 } 64 65 stage2(lua_State * L)66 int create_class::stage2(lua_State* L) 67 { 68 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1))); 69 assert((crep != 0) && "internal error, please report"); 70 assert((is_class_rep(L, lua_upvalueindex(1))) && "internal error, please report"); 71 72 #ifndef LUABIND_NO_ERROR_CHECKING 73 74 if (!is_class_rep(L, 1)) 75 { 76 lua_pushstring(L, "expected class to derive from or a newline"); 77 lua_error(L); 78 } 79 80 #endif 81 82 class_rep* base = static_cast<class_rep*>(lua_touserdata(L, 1)); 83 class_rep::base_info binfo; 84 85 binfo.pointer_offset = 0; 86 binfo.base = base; 87 crep->add_base_class(binfo); 88 89 // copy base class members 90 91 crep->get_table(L); 92 base->get_table(L); 93 copy_member_table(L); 94 95 crep->get_default_table(L); 96 base->get_default_table(L); 97 copy_member_table(L); 98 99 crep->set_type(base->type()); 100 101 return 0; 102 } 103 stage1(lua_State * L)104 int create_class::stage1(lua_State* L) 105 { 106 107 #ifndef LUABIND_NO_ERROR_CHECKING 108 109 if (lua_gettop(L) != 1 || lua_type(L, 1) != LUA_TSTRING || lua_isnumber(L, 1)) 110 { 111 lua_pushstring(L, "invalid construct, expected class name"); 112 lua_error(L); 113 } 114 115 if (std::strlen(lua_tostring(L, 1)) != lua_strlen(L, 1)) 116 { 117 lua_pushstring(L, "luabind does not support class names with extra nulls"); 118 lua_error(L); 119 } 120 121 #endif 122 123 const char* name = lua_tostring(L, 1); 124 125 void* c = lua_newuserdata(L, sizeof(class_rep)); 126 new(c) class_rep(L, name); 127 128 // make the class globally available 129 lua_pushstring(L, name); 130 lua_pushvalue(L, -2); 131 lua_settable(L, LUA_GLOBALSINDEX); 132 133 // also add it to the closure as return value 134 lua_pushcclosure(L, &stage2, 1); 135 136 return 1; 137 } 138 139 }} 140 141