diff options
| author | realtradam <[email protected]> | 2022-03-07 18:33:20 -0500 |
|---|---|---|
| committer | realtradam <[email protected]> | 2022-03-07 18:33:20 -0500 |
| commit | 9d440b24a50b54b1708123d77679477b14c4b3c0 (patch) | |
| tree | c75ddb2d8d1289a4768274e93822f862e0be44bf | |
| parent | 779d9f17adf189b45c6be2a4b3d0959019c5ad03 (diff) | |
| download | FelBind-9d440b24a50b54b1708123d77679477b14c4b3c0.tar.gz FelBind-9d440b24a50b54b1708123d77679477b14c4b3c0.zip | |
added some struct wrapping methods
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | generate.rb | 26 | ||||
| -rw-r--r-- | scan.rb | 6 | ||||
| -rw-r--r-- | templates.rb | 67 |
4 files changed, 80 insertions, 20 deletions
@@ -1,5 +1,6 @@ json.json raylib.h +chipmunk.h result.txt output output/* diff --git a/generate.rb b/generate.rb index 5889139..30ab22a 100644 --- a/generate.rb +++ b/generate.rb @@ -1,7 +1,6 @@ require 'optparse' require 'json' -require 'set' -require 'active_record' +require 'active_record' # use to make strings to snake_case. probably overkill require_relative './templates.rb' options = {} @@ -20,8 +19,6 @@ end.parse! options[:glue] ||= './glue.json' glue = JSON.parse(File.read(options[:glue])) -bound = {} - $phase1 = {} $phase2 = {} $phase3 = {} @@ -46,24 +43,23 @@ includes = %{ } defines = "" init_body = "" -standard_types = ['bool', 'int', 'float', 'double', 'float', 'const char *', 'unsigned int', 'void'] # for displaying statistics glue.first.each do |func, params| if (func.rpartition(' ').first == 'void') && (params[0] == 'void') $phase1[func] = params - elsif (standard_types.include? func.rpartition(' ').first) && (params[0] == 'void') + elsif (Tplt.non_struct_types.include? func.rpartition(' ').first) && (params[0] == 'void') $phase2[func] = params else no_struct_param = true params.each do |param| - if !(standard_types.include? param.rpartition(' ').first) + if !(Tplt.non_struct_types.include? param.rpartition(' ').first) no_struct_param = false break end end if no_struct_param - if standard_types.include? func.rpartition(' ').first + if Tplt.non_struct_types.include? func.rpartition(' ').first $phase3[func] = params else $phase4[func] = params @@ -106,28 +102,26 @@ glue.first.each do |func, params| defines += Tplt.function(func_name, body) init_body += Tplt.init_module_function('test', Tplt.rubify_func_name(func_name), func_name, "MRB_ARGS_NONE()") - bound[func] = params debug_mark_binding(func, params) # if phase 2 - elsif (standard_types.include? func_datatype) && (params[0] == 'void') + elsif (Tplt.non_struct_types.include? func_datatype) && (params[0] == 'void') body = Tplt.return_format(func, params) #defines += 'PHASE 2\n' defines += Tplt.function(func_name, body) init_body += Tplt.init_module_function('test', Tplt.rubify_func_name(func_name), func_name, "MRB_ARGS_NONE()") - bound[func] = params debug_mark_binding(func, params) - elsif standard_types.include? func_datatype # accept params + else Tplt.non_struct_types.include? func_datatype # accept params # detecting if there is no struct param(wont need this in the future) no_struct_param = true params.each do |param| - if !(standard_types.include? param.rpartition(' ').first) + if !(Tplt.non_struct_types.include? param.rpartition(' ').first) no_struct_param = false break end end if no_struct_param - if standard_types.include? func.rpartition(' ').first + if Tplt.non_struct_types.include? func.rpartition(' ').first #$phase3[func] = params # --- #body = '' @@ -152,9 +146,11 @@ glue.first.each do |func, params| init_body += Tplt.init_module_function('test', Tplt.rubify_func_name(func_name), func_name, "MRB_ARGS_OPT(1)") # opt stuff isnt correct, need to look at this again # --- #puts func - bound[func] = params debug_mark_binding(func, params) else + #puts func + #puts params + #puts '---' #$phase4[func] = params end else @@ -1,11 +1,13 @@ require 'json' +file_to_scan = 'raylib.h' + # ctags --list-kinds=c # p function prototypes # s structure names # z function parameters inside function or prototype definitions # m struct, and union members -parse = `ctags --output-format=json --c-kinds=pm --fields=+S --language-force=c raylib.h` +parse = `ctags --output-format=json --c-kinds=pm --fields=+S --language-force=c #{file_to_scan}` File.write('json.json', parse) $garbage = [] @@ -38,7 +40,7 @@ def parse_header(path) [functions, structs] end -functions, structs = parse_header('raylib.h') +functions, structs = parse_header(file_to_scan) def debug_show(type, hash) puts "#{type.upcase}:" diff --git a/templates.rb b/templates.rb index 6f753af..4378681 100644 --- a/templates.rb +++ b/templates.rb @@ -14,12 +14,31 @@ mrb_mruby_#{gem_name}_gem_final(mrb_state* mrb) { } end + def non_struct_types + @non_struct_types ||= ['bool', 'int', 'float', 'double', 'float', 'const char *', 'unsigned int', 'void'] + end + + def init_module(module_name) + "struct RClass *#{module_name.downcase}_module = mrb_define_module(mrb, \"#{module_name}\");" + end + def init_module_function(module_name, function_name, mrb_function_name, mrb_args) %{ mrb_define_module_function(mrb, #{module_name}, "#{function_name}", mrb_#{mrb_function_name}, #{mrb_args}); } end + # define under needs the C name, not the ruby name which may be confusing + def init_class(class_name, define_under, is_struct_wrapper = true) + %{ +struct RClass *#{class_name.downcase}_class = mrb_define_class_under(mrb, #{define_under}, \"#{class_name}\", mrb->object_class);"#{ + if is_struct_wrapper + "\nMRB_SET_INSTANCE_TT(#{class_name.downcase}_class, MRB_TT_DATA);" + end + } + } + end + def function(function_name, body) %{ static mrb_value @@ -58,10 +77,20 @@ if (mrb_undef_p(kw_values[#{kwarg_iter}])) { } end + def unwrap_struct(var_name, target, mrb_type, type) %{#{var_name} = DATA_GET_PTR(mrb, #{target}, &#{mrb_type}, #{type})} end + def wrap_struct(var_name, target, mrb_type, type) + %{ +#{var_name} = (#{type} *)DATA_PTR(#{target}) +if(#{var_name}) #{'{'} mrb_free(mrb, #{var_name}); #{'}'} +mrb_data_init(#{target}, NULL, &#{mrb_type}); +#{var_name} = (#{type} *)mrb_malloc(mrb, sizeof(#{type})); + } + end + def define_module(module_name) %{struct RClass *#{module_name.downcase} = mrb_define_module(mrb, "#{module_name}"); } @@ -93,7 +122,8 @@ if (mrb_undef_p(kw_values[#{kwarg_iter}])) { end end - # make a function named like a ruby one would + # convert a C function name to be + # formatted like a Ruby method name def rubify_func_name(function) func = function.underscore if func.start_with? 'is_' @@ -102,7 +132,7 @@ if (mrb_undef_p(kw_values[#{kwarg_iter}])) { func.delete_prefix('get_') end - # generate a return + # generate a return of a ruby bound C function def return_format(function, params) func_rpart = function.rpartition(' ') func_datatype = func_rpart.first @@ -112,7 +142,7 @@ if (mrb_undef_p(kw_values[#{kwarg_iter}])) { if params.first == 'void' result = "#{func_name}();\nreturn mrb_nil_value();" else - result = "#{func_name}(" #);\nreturn mrb_nil_value();" + result = "#{func_name}(" result += params.first.rpartition(' ').last params.drop(1).each do |param| @@ -133,6 +163,37 @@ if (mrb_undef_p(kw_values[#{kwarg_iter}])) { result end + # wrapping an existing struct to be used by ruby + def init_struct_wrapper(struct, free_body = nil) + %{ + #{"void mrb_helper_#{struct}_free(mrb_state*, void*);" if free_body} + +static const struct mrb_data_type mrb_#{struct}_struct = { +"#{struct}", +#{ + if free_body + "mrb_helper_#{struct}_free" + else + "mrb_free" + end +} + }; + #{ + if free_body + + %{ + void + mrb_helper_#{struct}_free(mrb_state* mrb, void*ptr) { +#{struct} *struct_data = (#{struct}*)ptr; +#{free_body} +mrb_free(mrb, ptr); + } + } + end + } + } + end + end end |
