diff options
| author | realtradam <[email protected]> | 2023-05-26 01:02:14 -0400 |
|---|---|---|
| committer | realtradam <[email protected]> | 2023-05-26 01:02:14 -0400 |
| commit | 24ba42e49f78fa9db482ecb967aca9b924f65fbf (patch) | |
| tree | ec513f36f8d3a2b41c147154812ab50b32259997 | |
| parent | 87727cdfbcb3d93f2a3216ab8dc20f40d5cfe985 (diff) | |
| download | FelBind-24ba42e49f78fa9db482ecb967aca9b924f65fbf.tar.gz FelBind-24ba42e49f78fa9db482ecb967aca9b924f65fbf.zip | |
broken struct binding
| -rw-r--r-- | ideas/stuff.rb | 2 | ||||
| -rw-r--r-- | lib/FelBind.rb | 135 |
2 files changed, 134 insertions, 3 deletions
diff --git a/ideas/stuff.rb b/ideas/stuff.rb index 276a101..9e4cba7 100644 --- a/ideas/stuff.rb +++ b/ideas/stuff.rb @@ -56,7 +56,7 @@ mgem = BindGem.new mgem.add_class("Color") -mgem.add_struct(class: "Color") do |struct| +mgem.add_struct(class: "Color", cstruct_name: "Color") do |struct| struct.initializer = true struct.member( name: "r", diff --git a/lib/FelBind.rb b/lib/FelBind.rb index 1ca1cff..51562fa 100644 --- a/lib/FelBind.rb +++ b/lib/FelBind.rb @@ -27,6 +27,117 @@ module FelBind block.call(functions.last) end + def add_struct(class_name:, cstruct_name:, &block) + structs.push StructObj.new(class_name, cstruct_name) + block.call(structs.last) + end + + # structs + class StructObj + attr_accessor :class_name, :cstruct_name, :initializer + + # declaring the C struct + def build_struct_init + "static const struct mrb_data_type felbind_struct_#{class_name} = { \"#{class_name}\", mrb_free };\n" + end + + # building the C functions + def build_funcs + init_result = "" + init_vars = "" + init_get_args_types = "" + init_get_args_addresses = "" + init_set_vars = "" + accessor_result = "" + if initializer + init_result += "static mrb_value felbind_struct_init_#{class_name}(mrb_state* mrb, mrb_value self) {\n" + init_result += "#{cstruct_name} *felbind_struct_wrapped_#{class_name} = (#{cstruct_name} *)DATA_PTR(self);\n" + init_result += "if(felbind_struct_wrapped_#{class_name}) { mrb_free(mrb, felbind_struct_wrapped_#{class_name}); }\n" + init_result += "mrb_data_init(self, NULL, &felbind_struct_#{class_name});\n" + init_result += "felbind_struct_wrapped_#{class_name} = (#{cstruct_name} *)mrb_malloc(mrb, sizeof(#{cstruct_name}));\n" + end + members.each do |mem| + next if !mem.accessor + next if !initializer + + if mem.rtype == "int" + init_vars += "mrb_int felbind_param_#{mem.name};\n" + init_get_args_types += "i" + init_get_args_addresses += ", &felbind_param_#{mem.name}" + init_set_vars += "felbind_struct_wrapped_#{class_name}->#{mem.name} = (#{mem.ctype})felbind_param_#{mem.name};\n" + + accessor_result += "static mrb_value felbind_getter_#{class_name}_#{mem.name}(mrb_state *mrb, mrb_value self) {\n" + accessor_result += "struct #{cstruct_name} *felbind_struct_get = DATA_GET_PTR(mrb, self, &felbind_struct_#{class_name}, #{cstruct_name});\n" + #accessor_result += "return mrb_fixnum_value(felbind_getter_#{class_name}_#{mem.name});\n" + accessor_result += "return mrb_fixnum_value(felbind_struct_get->#{mem.name});\n" + accessor_result += "}\n" + + accessor_result += "static mrb_value felbind_setter_#{class_name}_#{mem.name}(mrb_state *mrb, mrb_value self) {\n" + accessor_result += "mrb_int felbind_param_#{mem.name};\n" + accessor_result += "mrb_get_args(mrb, \"i\", &felbind_param_#{mem.name});\n" + accessor_result += "struct #{cstruct_name} *felbind_struct_set = DATA_GET_PTR(mrb, self, &felbind_struct_#{class_name}, #{cstruct_name});\n" + accessor_result += "felbind_struct_set->#{mem.name} = (#{mem.ctype})felbind_param_#{mem.name};\n" + accessor_result += "return mrb_fixnum_value(felbind_struct_set->#{mem.name});\n" + accessor_result += "}\n" + end + end + result = init_result + result += init_vars + result += "mrb_get_args(mrb, \"#{init_get_args_types}\"#{init_get_args_addresses});\n" + result += init_set_vars + result += "mrb_data_init(self, felbind_struct_wrapped_#{class_name}, &felbind_struct_#{class_name});\n" + result += "return self;\n" + result += "}\n" + result + accessor_result + end + + # binding instance after class is defined + def build_set_instance(def_class_name) + "MRB_SET_INSTANCE_TT(#{def_class_name}, MRB_TT_DATA);\n" + end + + # binding the C funcs to Ruby + def build_def_funcs(def_class_name) + result = "" + if initializer + result += "mrb_define_method(mrb, #{def_class_name}, \"initialize\", felbind_struct_init_#{class_name}, MRB_ARGS_ANY());\n" + end + members.each do |mem| + next if !initializer + next if !mem.accessor + + result += "mrb_define_method(mrb, #{def_class_name}, \"#{mem.name}\", felbind_getter_#{class_name}_#{mem.name}, MRB_ARGS_NONE());\n" + result += "mrb_define_method(mrb, #{def_class_name}, \"#{mem.name}=\", felbind_setter_#{class_name}_#{mem.name}, MRB_ARGS_ANY());\n" + end + result + end + + def initialize(class_name, cstruct_name) + self.class_name = class_name + self.cstruct_name = cstruct_name + end + + def members + @members ||= [] + end + + def member(name:, ctype:, rtype:, accessor:) + members.push MemberObj.new(name, ctype, rtype, accessor) + end + + # members + class MemberObj + attr_accessor :name, :ctype, :rtype, :accessor + + def initialize(name, ctype, rtype, accessor) + self.name = name + self.ctype = ctype + self.rtype = rtype + self.accessor = accessor + end + end + end + private def functions @@ -37,6 +148,10 @@ module FelBind @class_names ||= [] end + def structs + @structs ||= [] + end + # function class Function attr_accessor :content, :name, :class_name, :return_call_val, :args @@ -77,7 +192,7 @@ module FelBind end def arg(name) - "felflame_var_#{name}" + "felbind_var_#{name}" end def get_args(&block) @@ -116,9 +231,16 @@ module FelBind def build result = "" result += insert_includes + + structs.each do |strct| + result += strct.build_struct_init + result += strct.build_funcs + end + functions.each do |func_obj| result += func_obj.build end + result += build_init result += build_final result @@ -127,7 +249,11 @@ module FelBind private def insert_includes - "#include <mruby.h>\n#include <stdio.h>\n" + "#include <mruby.h>\n" + + "#include <mruby/data.h>\n" + + "#include <mruby/class.h>\n" + + "#include <mruby/compile.h>\n" + + "#include <stdio.h>\n" end def build_init @@ -136,6 +262,11 @@ module FelBind class_names.each do |class_name| result += "struct RClass *#{class_name}_class = mrb_define_module(mrb, \"#{class_name}\");\n" end + structs.each do |strct| + result += strct.build_set_instance("#{strct.class_name}_class") + result += strct.build_def_funcs("#{strct.class_name}_class") + end + functions.each do |func| result += "mrb_define_class_method(mrb, #{func.class_name}_class, \"#{func.name}\", felbind_#{func.name}," if(func.args.arguments.size.zero?) |
