summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrealtradam <[email protected]>2023-05-26 01:02:14 -0400
committerrealtradam <[email protected]>2023-05-26 01:02:14 -0400
commit24ba42e49f78fa9db482ecb967aca9b924f65fbf (patch)
treeec513f36f8d3a2b41c147154812ab50b32259997
parent87727cdfbcb3d93f2a3216ab8dc20f40d5cfe985 (diff)
downloadFelBind-24ba42e49f78fa9db482ecb967aca9b924f65fbf.tar.gz
FelBind-24ba42e49f78fa9db482ecb967aca9b924f65fbf.zip
broken struct binding
-rw-r--r--ideas/stuff.rb2
-rw-r--r--lib/FelBind.rb135
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?)