1 // Copyright (c) 2004 Daniel Wallin and Arvid Norberg
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:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
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.
23 #include <luabind/lua_include.hpp>
25 #include <luabind/config.hpp>
26 #include <luabind/class.hpp>
27 #include <luabind/nil.hpp>
34 LUABIND_API
detail::nil_type nil
;
37 namespace luabind
{ namespace detail
{
41 method_name(char const* n
): name(n
) {}
42 bool operator()(method_rep
const& o
) const
43 { return std::strcmp(o
.name
, name
) == 0; }
47 struct class_registration
: registration
49 class_registration(char const* name
);
51 void register_(lua_State
* L
) const;
55 mutable std::list
<detail::method_rep
> m_methods
;
57 // datamembers, some members may be readonly, and
58 // only have a getter function
59 mutable std::map
<const char*, detail::class_rep::callback
, detail::ltstr
> m_getters
;
60 mutable std::map
<const char*, detail::class_rep::callback
, detail::ltstr
> m_setters
;
62 // the operators in lua
63 mutable std::vector
<detail::class_rep::operator_callback
> m_operators
[detail::number_of_operators
];
64 mutable std::map
<const char*, int, detail::ltstr
> m_static_constants
;
66 mutable std::vector
<class_base::base_desc
> m_bases
;
67 mutable detail::construct_rep m_constructor
;
69 void(*m_destructor
)(void*);
70 void(*m_const_holder_destructor
)(void*);
72 void*(*m_extractor
)(void*);
73 const void*(*m_const_extractor
)(void*);
75 void(*m_const_converter
)(void*,void*);
77 void(*m_construct_holder
)(void*, void*);
78 void(*m_construct_const_holder
)(void*, void*);
80 void(*m_default_construct_holder
)(void*);
81 void(*m_default_construct_const_holder
)(void*);
83 void(*m_adopt_fun
)(void*);
86 int m_holder_alignment
;
88 LUABIND_TYPE_INFO m_type
;
89 LUABIND_TYPE_INFO m_holder_type
;
90 LUABIND_TYPE_INFO m_const_holder_type
;
95 class_registration::class_registration(char const* name
)
100 void class_registration::register_(lua_State
* L
) const
102 LUABIND_CHECK_STACK(L
);
104 assert(lua_type(L
, -1) == LUA_TTABLE
);
106 lua_pushstring(L
, m_name
);
108 detail::class_rep
* crep
;
110 detail::class_registry
* r
= detail::class_registry::get_registry(L
);
111 // create a class_rep structure for this class.
112 // allocate it within lua to let lua collect it on
113 // lua_close(). This is better than allocating it
114 // as a static, since it will then be destructed
115 // when the program exits instead.
116 // warning: we assume that lua will not
117 // move the userdata memory.
118 lua_newuserdata(L
, sizeof(detail::class_rep
));
119 crep
= reinterpret_cast<detail::class_rep
*>(lua_touserdata(L
, -1));
121 new(crep
) detail::class_rep(
126 , m_const_holder_destructor
128 , m_const_holder_type
133 , m_construct_const_holder
134 , m_default_construct_holder
135 , m_default_construct_const_holder
138 , m_holder_alignment
);
140 // register this new type in the class registry
141 r
->add_class(m_type
, crep
);
142 if (!(LUABIND_TYPE_INFO_EQUAL(m_holder_type
, LUABIND_INVALID_TYPE_INFO
)))
144 // if we have a held type
145 // we have to register it in the class-table
146 // but only for the base class, if it already
147 // exists, we don't have to register it
148 detail::class_rep
* c
= r
->find_class(m_holder_type
);
151 r
->add_class(m_holder_type
, crep
);
152 r
->add_class(m_const_holder_type
, crep
);
157 m_constructor
.swap(crep
->m_constructor
);
159 crep
->m_getters
.swap(m_getters
);
160 crep
->m_setters
.swap(m_setters
);
162 for (int i
= 0; i
< detail::number_of_operators
; ++i
)
163 crep
->m_operators
[i
].swap(m_operators
[i
]);
165 crep
->m_static_constants
.swap(m_static_constants
);
167 typedef std::list
<detail::method_rep
> methods_t
;
169 detail::class_registry
* registry
= detail::class_registry::get_registry(L
);
171 for (std::vector
<class_base::base_desc
>::iterator i
= m_bases
.begin();
172 i
!= m_bases
.end(); ++i
)
174 LUABIND_CHECK_STACK(L
);
176 // the baseclass' class_rep structure
177 detail::class_rep
* bcrep
= registry
->find_class(i
->type
);
179 detail::class_rep::base_info base
;
180 base
.pointer_offset
= i
->ptr_offset
;
183 crep
->add_base_class(base
);
185 // copy base class table
190 while (lua_next(L
, -2))
192 lua_pushvalue(L
, -2); // copy key
198 // copy base class detaults table
199 crep
->get_default_table(L
);
200 bcrep
->get_default_table(L
);
203 while (lua_next(L
, -2))
205 lua_pushvalue(L
, -2); // copy key
214 for (std::list
<detail::method_rep
>::iterator i
215 = m_methods
.begin(); i
!= m_methods
.end(); ++i
)
217 LUABIND_CHECK_STACK(L
);
218 crep
->add_method(*i
);
221 crep
->register_methods(L
);
225 crep
->get_default_table(L
);
226 m_scope
.register_(L
);
232 // -- interface ---------------------------------------------------------
234 class_base::class_base(char const* name
)
235 : scope(std::auto_ptr
<registration
>(
236 m_registration
= new class_registration(name
))
241 void class_base::init(
242 LUABIND_TYPE_INFO type_id
243 , LUABIND_TYPE_INFO holder_type
244 , LUABIND_TYPE_INFO const_holder_type
245 , void*(*extractor
)(void*)
246 , const void*(*const_extractor
)(void*)
247 , void(*const_converter_
)(void*,void*)
248 , void(*holder_constructor_
)(void*,void*)
249 , void(*const_holder_constructor_
)(void*,void*)
250 , void(*holder_default_constructor_
)(void*)
251 , void(*const_holder_default_constructor_
)(void*)
252 , void(*adopt_fun
)(void*)
253 , void(*destructor
)(void*)
254 , void(*const_holder_destructor
)(void*)
256 , int holder_alignment
)
258 m_registration
->m_type
= type_id
;
259 m_registration
->m_holder_type
= holder_type
;
260 m_registration
->m_const_holder_type
= const_holder_type
;
261 m_registration
->m_extractor
= extractor
;
262 m_registration
->m_const_extractor
= const_extractor
;
263 m_registration
->m_const_converter
= const_converter_
;
264 m_registration
->m_construct_holder
= holder_constructor_
;
265 m_registration
->m_construct_const_holder
= const_holder_constructor_
;
266 m_registration
->m_default_construct_holder
= holder_default_constructor_
;
267 m_registration
->m_default_construct_const_holder
= const_holder_default_constructor_
;
268 m_registration
->m_destructor
= destructor
;
269 m_registration
->m_const_holder_destructor
= const_holder_destructor
;
270 m_registration
->m_adopt_fun
= adopt_fun
;
271 m_registration
->m_holder_size
= holder_size
;
272 m_registration
->m_holder_alignment
= holder_alignment
;
275 void class_base::add_getter(
276 const char* name
, const boost::function2
<int, lua_State
*, int>& g
)
278 detail::class_rep::callback c
;
280 c
.pointer_offset
= 0;
282 const char* key
= name
;
283 m_registration
->m_getters
[key
] = c
;
286 #ifdef LUABIND_NO_ERROR_CHECKING
287 void class_base::add_setter(
289 , const boost::function2
<int, lua_State
*, int>& s
)
291 void class_base::add_setter(
293 , const boost::function2
<int, lua_State
*, int>& s
294 , int (*match
)(lua_State
*, int)
295 , void (*get_sig_ptr
)(lua_State
*, std::string
&))
298 detail::class_rep::callback c
;
300 c
.pointer_offset
= 0;
302 #ifndef LUABIND_NO_ERROR_CHECKING
308 const char* key
= name
;
309 m_registration
->m_setters
[key
] = c
;
312 void class_base::add_base(const base_desc
& b
)
314 m_registration
->m_bases
.push_back(b
);
317 void class_base::add_constructor(const detail::construct_rep::overload_t
& o
)
319 m_registration
->m_constructor
.overloads
.push_back(o
);
322 void class_base::add_method(const char* name
, const detail::overload_rep
& o
)
324 typedef std::list
<detail::method_rep
> methods_t
;
326 methods_t::iterator m
= std::find_if(
327 m_registration
->m_methods
.begin()
328 , m_registration
->m_methods
.end()
329 , method_name(name
));
330 if (m
== m_registration
->m_methods
.end())
332 m_registration
->m_methods
.push_back(method_rep());
333 m
= m_registration
->m_methods
.end();
342 #ifndef LUABIND_NO_ERROR_CHECKING
343 void class_base::add_operator(
344 int op_id
, int(*func
)(lua_State
*), int(*matcher
)(lua_State
*)
345 , void(*sig
)(lua_State
*, std::string
&), int arity
)
347 void class_base::add_operator(
348 int op_id
, int(*func
)(lua_State
*)
349 , int(*matcher
)(lua_State
*), int arity
)
352 detail::class_rep::operator_callback o
;
354 o
.set_match_fun(matcher
);
357 #ifndef LUABIND_NO_ERROR_CHECKING
362 m_registration
->m_operators
[op_id
].push_back(o
);
365 const char* class_base::name() const
367 return m_registration
->m_name
;
370 void class_base::add_static_constant(const char* name
, int val
)
372 m_registration
->m_static_constants
[name
] = val
;
375 void class_base::add_inner_scope(scope
& s
)
377 m_registration
->m_scope
.operator,(s
);
381 void add_custom_name(T i
, std::string
& s
) {}
383 void add_custom_name(std::type_info
const* i
, std::string
& s
)
390 std::string
get_class_name(lua_State
* L
, LUABIND_TYPE_INFO i
)
396 class_registry
* r
= class_registry::get_registry(L
);
397 class_rep
* crep
= r
->find_class(i
);
402 add_custom_name(i
, ret
);
406 if (LUABIND_TYPE_INFO_EQUAL(i
, crep
->holder_type()))
412 else if (LUABIND_TYPE_INFO_EQUAL(i
, crep
->const_holder_type()))
414 ret
+= "smart_ptr<const ";
426 }} // namespace luabind::detail