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 #define LUABIND_BUILDING
27 #include <luabind/config.hpp>
28 #include <luabind/class.hpp>
30 namespace luabind
{ namespace detail
{
32 struct class_registration
: registration
34 class_registration(char const* name
);
36 void register_(lua_State
* L
) const;
40 mutable std::map
<const char*, detail::method_rep
, detail::ltstr
> m_methods
;
42 // datamembers, some members may be readonly, and
43 // only have a getter function
44 mutable std::map
<const char*, detail::class_rep::callback
, detail::ltstr
> m_getters
;
45 mutable std::map
<const char*, detail::class_rep::callback
, detail::ltstr
> m_setters
;
47 // the operators in lua
48 mutable std::vector
<detail::class_rep::operator_callback
> m_operators
[detail::number_of_operators
];
49 mutable std::map
<const char*, int, detail::ltstr
> m_static_constants
;
51 mutable std::vector
<class_base::base_desc
> m_bases
;
52 mutable detail::construct_rep m_constructor
;
54 void(*m_destructor
)(void*);
55 void(*m_const_holder_destructor
)(void*);
57 void*(*m_extractor
)(void*);
58 const void*(*m_const_extractor
)(void*);
60 void(*m_const_converter
)(void*,void*);
62 void(*m_construct_holder
)(void*, void*);
63 void(*m_construct_const_holder
)(void*, void*);
66 int m_holder_alignment
;
68 LUABIND_TYPE_INFO m_type
;
69 LUABIND_TYPE_INFO m_holder_type
;
70 LUABIND_TYPE_INFO m_const_holder_type
;
72 #ifndef LUABIND_DONT_COPY_STRINGS
73 // the maps that contains char pointers points into
74 // this vector of strings.
75 mutable std::vector
<char*> m_strings
;
80 class_registration::class_registration(char const* name
)
82 #ifndef LUABIND_DONT_COPY_STRINGS
83 m_strings
.push_back(detail::dup_string(name
));
84 m_name
= m_strings
.back();
90 void class_registration::register_(lua_State
* L
) const
92 lua_pushstring(L
, m_name
);
94 detail::class_rep
* crep
;
96 detail::class_registry
* r
= detail::class_registry::get_registry(L
);
97 // create a class_rep structure for this class.
98 // allocate it within lua to let lua collect it on
99 // lua_close(). This is better than allocating it
100 // as a static, since it will then be destructed
101 // when the program exits instead.
102 // warning: we assume that lua will not
103 // move the userdata memory.
104 lua_newuserdata(L
, sizeof(detail::class_rep
));
105 crep
= reinterpret_cast<detail::class_rep
*>(lua_touserdata(L
, -1));
107 new(crep
) detail::class_rep(
112 , m_const_holder_destructor
114 , m_const_holder_type
119 , m_construct_const_holder
121 , m_holder_alignment
);
123 // register this new type in the class registry
124 r
->add_class(m_type
, crep
);
125 if (!(LUABIND_TYPE_INFO_EQUAL(m_holder_type
, LUABIND_INVALID_TYPE_INFO
)))
127 // if we have a held type
128 // we have to register it in the class-table
129 // but only for the base class, if it already
130 // exists, we don't have to register it
131 detail::class_rep
* c
= r
->find_class(m_holder_type
);
134 r
->add_class(m_holder_type
, crep
);
135 r
->add_class(m_const_holder_type
, crep
);
140 m_constructor
.swap(crep
->m_constructor
);
142 #ifndef LUABIND_DONT_COPY_STRINGS
143 assert(crep
->m_strings
.empty() && "Internal error");
144 crep
->m_strings
.swap(m_strings
);
147 crep
->m_getters
.swap(m_getters
);
148 crep
->m_setters
.swap(m_setters
);
150 for(int i
= 0; i
< detail::number_of_operators
; ++i
)
151 crep
->m_operators
[i
].swap(m_operators
[i
]);
153 crep
->m_static_constants
.swap(m_static_constants
);
156 // crep->m_methods = m_methods;
158 for (std::vector
<class_base::base_desc
>::iterator i
= m_bases
.begin();
162 detail::class_registry
* r
= detail::class_registry::get_registry(L
);
164 // the baseclass' class_rep structure
165 detail::class_rep
* bcrep
= r
->find_class(i
->type
);
167 detail::class_rep::base_info base
;
168 base
.pointer_offset
= i
->ptr_offset
;
171 crep
->add_base_class(base
);
173 typedef std::map
<const char*, detail::method_rep
, detail::ltstr
> methods_t
;
175 for (methods_t::const_iterator i
176 = bcrep
->m_methods
.begin()
177 ; i
!= bcrep
->m_methods
.end()
180 detail::method_rep
& m
= m_methods
[i
->first
];
182 typedef std::vector
<detail::overload_rep
> overloads_t
;
184 for (overloads_t::const_iterator j
185 = i
->second
.overloads().begin()
186 ; j
!= i
->second
.overloads().end()
189 detail::overload_rep o
= *j
;
190 o
.add_offset(base
.pointer_offset
);
195 // copy base class table
196 detail::getref(L
, crep
->table_ref());
197 detail::getref(L
, bcrep
->table_ref());
200 while (lua_next(L
, -2))
202 lua_pushvalue(L
, -2); // copy key
210 crep
->m_methods
= m_methods
;
212 for (std::map
<const char*, detail::method_rep
, detail::ltstr
>::iterator i
213 = crep
->m_methods
.begin(); i
!= crep
->m_methods
.end(); ++i
)
215 i
->second
.crep
= crep
;
219 for (std::map
<const char*, detail::method_rep
, detail::ltstr
>::iterator i
220 = m_methods
.begin(); i
!= m_methods
.end(); ++i
)
222 detail::getref(L
, crep
->table_ref());
223 lua_pushstring(L
, i
->first
);
228 crep
->add_method(L
, i
->first
, crep
->m_methods
[i
->first
]);
229 i
->second
.crep
= crep
;
234 detail::getref(L
, crep
->table_ref());
235 m_scope
.register_(L
);
241 // -- interface ---------------------------------------------------------
243 class_base::class_base(char const* name
)
244 : scope(std::auto_ptr
<registration
>(
245 m_registration
= new class_registration(name
))
250 void class_base::init(
251 LUABIND_TYPE_INFO type_
252 , LUABIND_TYPE_INFO holder_type
253 , LUABIND_TYPE_INFO const_holder_type
254 , void*(*extractor
)(void*)
255 , const void*(*const_extractor
)(void*)
256 , void(*const_converter_
)(void*,void*)
257 , void(*holder_constructor_
)(void*,void*)
258 , void(*const_holder_constructor_
)(void*,void*)
259 , void(*destructor
)(void*)
260 , void(*const_holder_destructor
)(void*)
262 , int holder_alignment
)
264 m_registration
->m_type
= type_
;
265 m_registration
->m_holder_type
= holder_type
;
266 m_registration
->m_const_holder_type
= const_holder_type
;
267 m_registration
->m_extractor
= extractor
;
268 m_registration
->m_const_extractor
= const_extractor
;
269 m_registration
->m_const_converter
= const_converter_
;
270 m_registration
->m_construct_holder
= holder_constructor_
;
271 m_registration
->m_construct_const_holder
= const_holder_constructor_
;
272 m_registration
->m_destructor
= destructor
;
273 m_registration
->m_const_holder_destructor
= const_holder_destructor
;
274 m_registration
->m_holder_size
= holder_size
;
275 m_registration
->m_holder_alignment
= holder_alignment
;
278 void class_base::add_getter(
279 const char* name
, const boost::function2
<int, lua_State
*, int>& g
)
281 detail::class_rep::callback c
;
283 c
.pointer_offset
= 0;
285 #ifndef LUABIND_DONT_COPY_STRINGS
286 char* key
= detail::dup_string(name
);
287 m_registration
->m_strings
.push_back(key
);
289 const char* key
= name
;
291 m_registration
->m_getters
[key
] = c
;
294 #ifdef LUABIND_NO_ERROR_CHECKING
295 void class_base::add_setter(
297 , const boost::function2
<int, lua_State
*, int>& s
)
299 void class_base::add_setter(
301 , const boost::function2
<int, lua_State
*, int>& s
302 , int (*match
)(lua_State
*, int)
303 , void (*get_sig_ptr
)(lua_State
*, std::string
&))
306 detail::class_rep::callback c
;
308 c
.pointer_offset
= 0;
310 #ifndef LUABIND_NO_ERROR_CHECKING
315 #ifndef LUABIND_DONT_COPY_STRINGS
316 char* key
= detail::dup_string(name
);
317 m_registration
->m_strings
.push_back(key
);
319 const char* key
= name
;
321 m_registration
->m_setters
[key
] = c
;
324 void class_base::add_base(const base_desc
& b
)
326 m_registration
->m_bases
.push_back(b
);
329 void class_base::add_constructor(const detail::construct_rep::overload_t
& o
)
331 m_registration
->m_constructor
.overloads
.push_back(o
);
334 void class_base::add_method(const char* name
, const detail::overload_rep
& o
)
336 #ifdef LUABIND_DONT_COPY_STRINGS
337 detail::method_rep
& method
= m_registration
->m_methods
[name
];
340 m_registration
->m_strings
.push_back(detail::dup_string(name
));
341 detail::method_rep
& method
= m_registration
->m_methods
[
342 m_registration
->m_strings
.back()];
343 method
.name
= m_registration
->m_strings
.back();
345 method
.add_overload(o
);
349 #ifndef LUABIND_NO_ERROR_CHECKING
350 void class_base::add_operator(
351 int op_id
, int(*func
)(lua_State
*), int(*matcher
)(lua_State
*)
352 , void(*sig
)(lua_State
*, std::string
&), int arity
)
354 void class_base::add_operator(
355 int op_id
, int(*func
)(lua_State
*)
356 , int(*matcher
)(lua_State
*), int arity
)
359 detail::class_rep::operator_callback o
;
361 o
.set_match_fun(matcher
);
364 #ifndef LUABIND_NO_ERROR_CHECKING
369 m_registration
->m_operators
[op_id
].push_back(o
);
372 const char* class_base::name() const
374 return m_registration
->m_name
;
377 void class_base::add_static_constant(const char* name
, int val
)
379 m_registration
->m_static_constants
[name
] = val
;
382 void class_base::add_inner_scope(scope
& s
)
384 m_registration
->m_scope
.operator,(s
);
387 }} // namespace luabind::detail