def get_binding_api_declaration(self): type_info_name = gen.apply_api_prefix('type_info') out = '''\ struct %s { uint32_t type_tag; const char *c_type; const char *bound_name; bool (*check)(PyObject *o); void (*to_c)(PyObject *o, void *out); PyObject *(*from_c)(void *obj, OwnershipPolicy policy); };\n ''' % type_info_name out += '// return a type info from its bound name\n' out += '%s *%s(uint32_t type_tag);\n' % ( type_info_name, gen.apply_api_prefix('get_bound_type_info')) out += '// return a type info from its C name\n' out += '%s *%s(const char *type);\n' % ( type_info_name, gen.apply_api_prefix('get_c_type_info')) out += '// returns the typetag of a Python object, nullptr if not a Fabgen object\n' out += 'uint32_t %s(PyObject *o);\n\n' % gen.apply_api_prefix( 'get_wrapped_object_type_tag') return out
def get_binding_api_declaration(self): type_info_name = gen.apply_api_prefix('type_info') out = '''\ struct %s { uint32_t type_tag; const char *c_type; const char *bound_name; bool (*check)(lua_State *L, int index); void (*to_c)(lua_State *L, int index, void *out); int (*from_c)(lua_State *L, void *obj, OwnershipPolicy policy); };\n ''' % type_info_name out += '// return a type info from its type tag\n' out += '%s *%s(uint32_t type_tag);\n' % (type_info_name, gen.apply_api_prefix('get_bound_type_info')) out += '// return a type info from its type name\n' out += '%s *%s(const char *type);\n' % (type_info_name, gen.apply_api_prefix('get_c_type_info')) out += '// returns the typetag of a userdata object on the stack, nullptr if not a Fabgen object\n' out += 'uint32_t %s(lua_State *L, int idx);\n\n' % gen.apply_api_prefix('get_wrapped_object_type_tag') return out
def output_binding_api(self): type_info_name = gen.apply_api_prefix('type_info') self._source += '// Note: Types using a storage class for conversion are not listed here.\n' self._source += 'static std::map<uint32_t, %s> __type_tag_infos;\n\n' % type_info_name self._source += 'static void __initialize_type_tag_infos() {\n' entries = [] for type in self._bound_types: if not type.c_storage_class: self._source += ' __type_tag_infos[%s] = {%s, "%s", "%s", %s, %s, %s};\n' % ( type.type_tag, type.type_tag, str( type.ctype), type.bound_name, type.check_func, type.to_c_func, type.from_c_func) self._source += '};\n\n' self._source += '''\ %s *%s(uint32_t type_tag) { auto i = __type_tag_infos.find(type_tag); return i == __type_tag_infos.end() ? nullptr : &i->second; }\n\n''' % (type_info_name, gen.apply_api_prefix('get_bound_type_info')) self._source += 'static std::map<std::string, %s> __type_infos;\n\n' % type_info_name self._source += 'static void __initialize_type_infos() {\n' for type in self._bound_types: if not type.c_storage_class: self._source += ' __type_infos["%s"] = {%s, "%s", "%s", %s, %s, %s};\n' % ( str(type.ctype), type.type_tag, str( type.ctype), type.bound_name, type.check_func, type.to_c_func, type.from_c_func) self._source += '};\n\n' self._source += ''' %s *%s(const char *type) { auto i = __type_infos.find(type); return i == __type_infos.end() ? nullptr : &i->second; }\n\n''' % (type_info_name, gen.apply_api_prefix('get_c_type_info')) self._source += '''\ uint32_t %s(PyObject *o) { auto w = cast_to_wrapped_Object_safe(o); return w ? w->type_tag : 0; }\n\n''' % gen.apply_api_prefix('get_wrapped_object_type_tag')
def finalize(self): super().finalize() self.output_binding_api() # output module functions table self._source += 'static const luaL_Reg %s_global_functions[] = {\n' % self._name for f in self._bound_functions: self._source += ' {"%s", %s},\n' % (f['bound_name'], f['proxy_name']) self._source += ' {NULL, NULL}};\n\n' # registration function self._source += '''\ #if WIN32 #define _DLL_EXPORT_ __declspec(dllexport) #else #define _DLL_EXPORT_ #endif \n''' self._source += '''static void declare_enum_value(lua_State *L, int idx, const char *name, int value) { lua_pushinteger(L, value); lua_setfield(L, idx, name); }\n\n''' # variable lookup map self._source += build_index_map('__index_%s_var_map' % self._name, self._bound_variables, lambda v: True, lambda v: ' {"%s", %s}' % (v['bound_name'], v['getter'])) self._source += build_index_map('__newindex_%s_var_map' % self._name, self._bound_variables, lambda v: v['setter'], lambda v: ' {"%s", %s}' % (v['bound_name'], v['setter'])) self._source += '''\ static int __index_%s_var(lua_State *L) { if (lua_isstring(L, -1)) { std::string key = lua_tostring(L, -1); lua_pop(L, 1); auto i = __index_%s_var_map.find(key); // variable lookup if (i != __index_%s_var_map.end()) return i->second(L); } return 0; // lookup failed }\n\n''' % (self._name, self._name, self._name) self._source += '''\ static int __newindex_%s_var(lua_State *L) { if (lua_isstring(L, -2)) { std::string key = lua_tostring(L, -2); lua_remove(L, -2); auto i = __newindex_%s_var_map.find(key); if (i != __newindex_%s_var_map.end()) return i->second(L); } return 0; // lookup failed }\n\n''' % (self._name, self._name, self._name) self.output_module_free() self._source += '''\ static const luaL_Reg %s_module_meta[] = { {"__gc", __gc_%s}, {"__index", __index_%s_var}, {"__newindex", __newindex_%s_var}, {NULL, NULL} };\n\n''' % (self._name, self._name, self._name, self._name) # if self.embedded: # pragma: no cover create_module_func = gen.apply_api_prefix('create_%s' % self._name) bind_module_func = gen.apply_api_prefix('bind_%s' % self._name) self._header += '// create the module object and push it onto the stack\n' self._header += 'int %s(lua_State *L);\n' % create_module_func self._header += '// create the module object and register it into the interpreter global table\n' self._header += 'bool %s(lua_State *L, const char *symbol);\n\n' % bind_module_func self._source += 'int %s(lua_State *L) {\n' % create_module_func else: self._source += 'extern "C" _DLL_EXPORT_ int luaopen_%s(lua_State *L) {\n' % self._name self._source += ' // initialize type info structures\n' self._source += ' __initialize_type_tag_infos();\n' self._source += ' __initialize_type_infos();\n' self._source += '\n' self._source += ' // custom initialization code\n' self._source += self._custom_init_code self._source += '\n' # create the module table self._source += ' // new module table\n' self._source += ' lua_newtable(L);\n' self._source += '\n' # enums if len(self._enums) > 0: for name, enum in self._enums.items(): self._source += ' // enumeration %s\n' % name for name, value in enum.items(): self._source += ' declare_enum_value(L, -2, "%s", (int)%s);\n' % (name, value) self._source += '\n' types_to_register = [t for t in self._bound_types if isinstance(t, LuaClassTypeConverter)] if len(types_to_register) > 0: self._source += ' // register types\n' for t in types_to_register: self._source += ' register_%s(L);\n' % t.bound_name self._source += '\n' self._source += ' // register global functions\n' self._source += ' luaL_setfuncs(L, %s_global_functions, 0);\n' % self._name self._source += '\n' # module metatable self._source += ' // setup module metatable\n' self._source += ' lua_newtable(L);\n' self._source += ' luaL_setfuncs(L, %s_module_meta, 0);\n' % self._name self._source += ' lua_setmetatable(L, -2);\n' self._source += ' return 1;\n' self._source += '}\n\n' # if self.embedded: # pragma: no cover self._source += '''\ bool %s(lua_State *L, const char *symbol) { if (%s(L) != 1) return false; lua_setglobal(L, symbol); return true; }\n ''' % (bind_module_func, create_module_func)