summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrealtradam <[email protected]>2022-03-07 18:33:20 -0500
committerrealtradam <[email protected]>2022-03-07 18:33:20 -0500
commit9d440b24a50b54b1708123d77679477b14c4b3c0 (patch)
treec75ddb2d8d1289a4768274e93822f862e0be44bf
parent779d9f17adf189b45c6be2a4b3d0959019c5ad03 (diff)
downloadFelBind-9d440b24a50b54b1708123d77679477b14c4b3c0.tar.gz
FelBind-9d440b24a50b54b1708123d77679477b14c4b3c0.zip
added some struct wrapping methods
-rw-r--r--.gitignore1
-rw-r--r--generate.rb26
-rw-r--r--scan.rb6
-rw-r--r--templates.rb67
4 files changed, 80 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
index 5db0d93..174abc2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/scan.rb b/scan.rb
index 6a6d230..eda1284 100644
--- a/scan.rb
+++ b/scan.rb
@@ -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