5 #include "create_wrapper.hpp"
9 WrapperCreator::create_wrapper(Namespace* ns)
11 std::string fromfile = original_file != "" ? original_file : inputfile;
16 << " * WARNING: This file is automatically generated from:\n"
17 << " * '" << fromfile << "'\n"
18 << " * DO NOT CHANGE\n"
20 << "#ifndef __" << modulename << "_WRAPPER_H__\n"
21 << "#define __" << modulename << "_WRAPPER_H__\n"
23 << "#include <squirrel.h>\n"
25 if(selected_namespace != "") {
26 hppout << "namespace " << selected_namespace << "\n"
29 for(std::vector<AtomicType*>::iterator i = ns->types.begin();
30 i != ns->types.end(); ++i) {
31 AtomicType* type = *i;
32 Class* _class = dynamic_cast<Class*> (type);
36 hppout << "class " << _class->name << ";\n";
39 if(selected_namespace != "") {
44 << "namespace SquirrelWrapper\n"
48 if(selected_namespace != "") {
49 hppout << "using namespace " << selected_namespace << ";\n"
53 hppout << "void register_" << modulename << "_wrapper(HSQUIRRELVM v);\n"
56 for(std::vector<AtomicType*>::iterator i = ns->types.begin();
57 i != ns->types.end(); ++i) {
58 AtomicType* type = *i;
59 Class* _class = dynamic_cast<Class*> (type);
63 hppout << "void create_squirrel_instance(HSQUIRRELVM v, "
65 << "* object, bool setup_releasehook = false);\n";
75 << " * WARNING: This file is automatically generated from:\n"
76 << " * '" << fromfile << "'\n"
77 << " * DO NOT CHANGE\n"
79 << "#include <config.h>\n"
82 << "#include <assert.h>\n"
83 << "#include <string>\n"
84 << "#include <squirrel.h>\n"
85 << "#include \"wrapper_util.hpp\"\n"
86 << "#include \"wrapper.interface.hpp\"\n"
88 << "namespace SquirrelWrapper\n"
92 if(selected_namespace != "") {
93 out << "using namespace " << selected_namespace << ";\n";
97 for(std::vector<AtomicType*>::iterator i = ns->types.begin();
98 i != ns->types.end(); ++i) {
99 AtomicType* type = *i;
100 Class* _class = dynamic_cast<Class*> (type);
102 create_class_wrapper(_class);
104 for(std::vector<Function*>::iterator i = ns->functions.begin();
105 i != ns->functions.end(); ++i) {
106 create_function_wrapper(0, *i);
109 out << "void register_" << modulename << "_wrapper(HSQUIRRELVM v)\n"
111 << ind << "sq_pushroottable(v);\n";
113 create_register_constants_code(ns);
114 create_register_functions_code(ns);
115 create_register_classes_code(ns);
117 out << ind << "sq_pop(v, 1);\n"
125 WrapperCreator::create_register_function_code(Function* function, Class* _class)
127 if(function->type == Function::DESTRUCTOR)
130 out << ind << "sq_pushstring(v, \"" << function->name << "\", -1);\n";
131 out << ind << "sq_newclosure(v, &"
132 << (_class != 0 ? _class->name + "_" : "") << function->name
133 << "_wrapper, 0);\n";
134 create_register_slot_code("function", function->name);
139 WrapperCreator::create_register_functions_code(Namespace* ns)
141 for(std::vector<Function*>::iterator i = ns->functions.begin();
142 i != ns->functions.end(); ++i) {
143 Function* function = *i;
144 create_register_function_code(function, 0);
149 WrapperCreator::create_register_classes_code(Namespace* ns)
151 for(std::vector<AtomicType*>::iterator i = ns->types.begin();
152 i != ns->types.end(); ++i) {
153 AtomicType* type = *i;
154 Class* _class = dynamic_cast<Class*> (type);
157 if(_class->super_classes.size() > 0)
160 create_register_class_code(_class);
165 WrapperCreator::create_register_class_code(Class* _class)
167 out << ind << "// Register class " << _class->name << "\n";
168 out << ind << "sq_pushstring(v, \""
169 << _class->name << "\", -1);\n";
171 if(_class->super_classes.size() > 0) {
172 if(_class->super_classes.size() > 1) {
173 std::ostringstream msg;
174 msg << "Multiple inheritance not supported (at class '"
175 << _class->name << "')";
176 throw std::runtime_error(msg.str());
179 out << ind << "sq_pushstring(v, \""
180 << _class->super_classes[0]->name << "\", -1);\n";
181 out << ind << "sq_get(v, -3);\n";
183 out << ind << "if(sq_newclass(v, "
184 << (_class->super_classes.size() > 0 ? "SQTrue" : "SQFalse")
186 out << ind << ind << "std::ostringstream msg;\n";
187 out << ind << ind << "msg << \"Couldn't create new class '"
188 << _class->name << "'\";\n";
189 out << ind << ind << "throw SquirrelError(v, msg.str());\n";
192 for(std::vector<ClassMember*>::iterator i = _class->members.begin();
193 i != _class->members.end(); ++i) {
194 ClassMember* member = *i;
195 if(member->visibility != ClassMember::PUBLIC)
197 Function* function = dynamic_cast<Function*> (member);
199 create_register_function_code(function, _class);
201 Field* field = dynamic_cast<Field*> (member);
203 create_register_constant_code(field);
207 create_register_slot_code("class", _class->name);
210 for(std::vector<Class*>::iterator i = _class->sub_classes.begin();
211 i != _class->sub_classes.end(); ++i) {
213 create_register_class_code(_class);
218 WrapperCreator::create_register_constants_code(Namespace* ns)
220 for(std::vector<Field*>::iterator i = ns->fields.begin();
221 i != ns->fields.end(); ++i) {
223 create_register_constant_code(field);
228 WrapperCreator::create_register_constant_code(Field* field)
230 if(!field->has_const_value)
232 out << ind << "sq_pushstring(v, \"" << field->name << "\", -1);\n";
233 if(field->type->atomic_type == &BasicType::INT) {
234 out << ind << "sq_pushinteger(v, " << field->const_int_value << ");\n";
235 } else if(field->type->atomic_type == &BasicType::FLOAT) {
236 out << ind << "sq_pushfloat(v, " << field->const_float_value << ");\n";
237 } else if(field->type->atomic_type == StringType::instance()) {
238 out << ind << "sq_pushstring(v, \""
239 << field->const_string_value << "\", -1);\n";
241 throw std::runtime_error("Constant is not int, float or string");
243 create_register_slot_code("constant", field->name);
248 WrapperCreator::create_register_slot_code(const std::string& what,
249 const std::string& name)
251 out << ind << "if(sq_createslot(v, -3) < 0) {\n";
252 out << ind << ind << "std::ostringstream msg;\n";
253 out << ind << ind << "msg << \"Couldn't register " << what << "'"
255 out << ind << ind << "throw SquirrelError(v, msg.str());\n";
260 WrapperCreator::create_function_wrapper(Class* _class, Function* function)
262 if(function->type == Function::DESTRUCTOR)
265 std::string ns_prefix;
266 if(selected_namespace != "")
267 ns_prefix = selected_namespace + "::";
268 if(function->type == Function::CONSTRUCTOR)
269 function->name = "constructor";
271 out << "static int ";
273 out << _class->name << "_";
275 out << function->name << "_wrapper(HSQUIRRELVM v)\n"
278 if(_class == 0 && function->parameters.empty()
279 && function->return_type.is_void()
280 && function->type != Function::CONSTRUCTOR) {
281 out << ind << "(void) v;\n";
284 // eventually retrieve pointer to class instance
285 if(_class != 0 && function->type != Function::CONSTRUCTOR) {
286 out << ind << ns_prefix << _class->name << "* _this;\n";
287 out << ind << "sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);\n";
290 // declare and retrieve arguments
293 for(std::vector<Parameter>::iterator p = function->parameters.begin();
294 p != function->parameters.end(); ++p) {
295 if(i == 0 && p->type.atomic_type == HSQUIRRELVMType::instance()) {
296 out << ind << "HSQUIRRELVM arg0 = v;\n";
300 snprintf(argname, sizeof(argname), "arg%d", i);
301 prepare_argument(p->type, i + arg_offset, argname);
309 if(!function->return_type.is_void()) {
310 function->return_type.write_c_type(out);
311 out << " return_value = ";
314 if(function->type == Function::CONSTRUCTOR) {
315 out << ns_prefix << _class->name << "* _this = new " << ns_prefix;
322 if(function->type == Function::CONSTRUCTOR) {
323 out << _class->name << "(";
325 out << function->name << "(";
327 for(size_t i = 0; i < function->parameters.size(); ++i) {
333 if(function->type == Function::CONSTRUCTOR) {
334 out << ind << "sq_setinstanceup(v, 1, _this);\n";
335 out << ind << "sq_setreleasehook(v, 1, "
336 << _class->name << "_release_hook);\n";
339 // push return value back on stack and return
340 if(function->return_type.is_void()) {
341 if(function->docu_comment.find("@SUSPEND@") != std::string::npos) {
342 out << ind << "return sq_suspendvm(v);\n";
344 out << ind << "return 0;\n";
347 push_to_stack(function->return_type, "return_value");
348 out << ind << "return 1;\n";
355 WrapperCreator::prepare_argument(const Type& type, size_t index,
356 const std::string& var)
358 if(type.ref > 0 && type.atomic_type != StringType::instance())
359 throw std::runtime_error("References not handled yet");
361 throw std::runtime_error("Pointers not handled yet");
362 if(type.atomic_type == &BasicType::INT) {
363 out << ind << "int " << var << ";\n";
364 out << ind << "sq_getinteger(v, " << index << ", &" << var << ");\n";
365 } else if(type.atomic_type == &BasicType::FLOAT) {
366 out << ind << "float " << var << ";\n";
367 out << ind << "sq_getfloat(v, " << index << ", &" << var << ");\n";
368 } else if(type.atomic_type == &BasicType::BOOL) {
369 out << ind << "SQBool " << var << ";\n";
370 out << ind << "sq_getbool(v, " << index << ", &" << var << ");\n";
371 } else if(type.atomic_type == StringType::instance()) {
372 out << ind << "const char* " << var << ";\n";
373 out << ind << "sq_getstring(v, " << index << ", &" << var << ");\n";
375 std::ostringstream msg;
376 msg << "Type '" << type.atomic_type->name << "' not supported yet.";
377 throw std::runtime_error(msg.str());
382 WrapperCreator::push_to_stack(const Type& type, const std::string& var)
384 if(type.ref > 0 && type.atomic_type != StringType::instance())
385 throw std::runtime_error("References not handled yet");
387 throw std::runtime_error("Pointers not handled yet");
389 if(type.atomic_type == &BasicType::INT) {
390 out << "sq_pushinteger(v, " << var << ");\n";
391 } else if(type.atomic_type == &BasicType::FLOAT) {
392 out << "sq_pushfloat(v, " << var << ");\n";
393 } else if(type.atomic_type == &BasicType::BOOL) {
394 out << "sq_pushbool(v, " << var << ");\n";
395 } else if(type.atomic_type == StringType::instance()) {
396 out << "sq_pushstring(v, " << var << ".c_str(), "
397 << var << ".size());\n";
399 std::ostringstream msg;
400 msg << "Type '" << type.atomic_type->name << "' not supported yet.";
401 throw std::runtime_error(msg.str());
406 WrapperCreator::create_class_wrapper(Class* _class)
408 create_class_release_hook(_class);
409 create_squirrel_instance(_class);
410 for(std::vector<ClassMember*>::iterator i = _class->members.begin();
411 i != _class->members.end(); ++i) {
412 ClassMember* member = *i;
413 if(member->visibility != ClassMember::PUBLIC)
415 Function* function = dynamic_cast<Function*> (member);
418 // don't wrap destructors
419 if(function->type == Function::DESTRUCTOR)
421 create_function_wrapper(_class, function);
426 WrapperCreator::create_squirrel_instance(Class* _class)
428 out << "void create_squirrel_instance(HSQUIRRELVM v, "
430 << "* object, bool setup_releasehook)\n"
432 << ind << "sq_pushstring(v, \"" << _class->name << "\", -1);\n"
433 << ind << "if(sq_get(v, -2) < 0) {\n"
434 << ind << ind << "std::ostringstream msg;\n"
435 << ind << ind << "msg << \"Couldn't resolved squirrel type '"
436 << _class->name << "'\";\n"
437 << ind << ind << "throw SquirrelError(v, msg.str());\n"
440 << ind << "if(sq_createinstance(v, -1) < 0 || "
441 << "sq_setinstanceup(v, -1, object) < 0) {\n"
442 << ind << ind << "std::ostringstream msg;\n"
443 << ind << ind << "msg << \"Couldn't setup squirrel instance for "
444 << "object of type '" << _class->name << "'\";\n"
445 << ind << ind << "throw SquirrelError(v, msg.str());\n"
447 << ind << "sq_remove(v, -2);\n"
449 << ind << "if(setup_releasehook) {\n"
450 << ind << ind << "sq_setreleasehook(v, -1, "
451 << _class->name << "_release_hook);\n"
457 WrapperCreator::create_class_release_hook(Class* _class)
459 out << "static int " << _class->name << "_release_hook(SQUserPointer ptr, int )\n"
461 << ind << _class->name
462 << "* _this = reinterpret_cast<" << _class->name << "*> (ptr);\n"
463 << ind << "delete _this;\n"
464 << ind << "return 0;\n"