├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── class_under_module.c ├── class_under_module_mrb.rb ├── run_tests.sh ├── simple_class.c ├── simple_class_mrb.rb ├── simple_module.c ├── simple_module_mrb.rb ├── simple_yield.c ├── simple_yield_mrb.rb ├── simplest.c ├── simplest_mrb.rb └── test_output ├── class_under_module.tst ├── simple_class.tst ├── simple_module.tst ├── simple_yield.tst └── simplest.tst /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | 5 | # Libraries 6 | *.lib 7 | *.a 8 | 9 | # Shared objects (inc. Windows DLLs) 10 | *.dll 11 | *.so 12 | *.so.* 13 | *.dylib 14 | 15 | # Executables 16 | *.exe 17 | *.out 18 | *.app 19 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "mruby"] 2 | path = mruby 3 | url = https://github.com/mruby/mruby.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Carson McDonald 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BINS = simplest simple_module simple_class class_under_module simple_yield 2 | 3 | SRC := $(BINS:%=%.c) 4 | OBJS := $(BINS:%=%.o) 5 | MRB_HEADERS := $(BINS:%=%_mrb.h) 6 | MRB_SAMPLES := $(BINS:%=%_mrb.rb) 7 | 8 | all: $(BINS) 9 | 10 | $(MRB_HEADERS): $(MRB_SAMPLES) mruby/bin/mrbc 11 | mruby/bin/mrbc -B $* -o $*.h $*.rb 12 | 13 | $(OBJS): $(MRB_HEADERS) $(SRC) 14 | gcc -c $*.c -o $@ -Imruby/include 15 | 16 | $(BINS): $(OBJS) mruby/build/host/lib/libmruby.a 17 | gcc -o $@ $@.o -lmruby -lm -Lmruby/build/host/lib 18 | 19 | mruby/build/host/lib/libmruby.a: 20 | cd mruby; rake 21 | 22 | mruby/bin/mrbc: 23 | cd mruby; rake 24 | 25 | clean: 26 | rm -f $(BINS) 27 | rm -f *.o 28 | rm -f $(MRB_HEADERS) 29 | 30 | clean_all: clean 31 | cd mruby; rake clean 32 | 33 | test: $(BINS) 34 | ./run_tests.sh $(BINS) 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Embedding mruby in C 2 | ==================== 3 | 4 | Simple example of mruby embedded in a C application 5 | 6 | To get started with the simplest example you can do the following: 7 | 8 | ``` 9 | git clone --recursive https://github.com/carsonmcdonald/mruby-c-example.git 10 | cd mruby-c-example 11 | make 12 | ./simplest 13 | ``` 14 | 15 | Examples 16 | ======== 17 | 18 | * *simplest* - Simply load and run a script 19 | * *simple_class* - Create a class and use it in a script 20 | * *simple_module* - Create a module and use it in a script 21 | * *class_under_module* - Create a class under a module and use it in a script 22 | * *simple_yield* - Create a method that yields to a given block 23 | -------------------------------------------------------------------------------- /class_under_module.c: -------------------------------------------------------------------------------- 1 | #include "mruby.h" 2 | #include "mruby/irep.h" 3 | #include "mruby/string.h" 4 | 5 | #include "class_under_module_mrb.h" 6 | 7 | static mrb_value foo_bar_init(mrb_state* mrb, mrb_value self) 8 | { 9 | char *message = NULL; 10 | mrb_get_args(mrb, "z", &message); 11 | 12 | fprintf(stderr, "Foo::Bar initialized with: %s\n", message); 13 | 14 | return self; 15 | } 16 | 17 | static mrb_value foo_bar_baz(mrb_state* mrb, mrb_value obj) 18 | { 19 | char *message = NULL; 20 | mrb_get_args(mrb, "z", &message); 21 | 22 | fprintf(stderr, "baz: %s\n", message); 23 | 24 | return mrb_nil_value(); 25 | } 26 | 27 | int main(void) 28 | { 29 | mrb_state *mrb = mrb_open(); 30 | 31 | struct RClass *foo_module = mrb_define_module(mrb, "Foo"); 32 | 33 | struct RClass *foo_class = mrb_define_class_under(mrb, foo_module, "Bar", mrb->object_class); 34 | 35 | mrb_define_method(mrb, foo_class, "initialize", foo_bar_init, MRB_ARGS_REQ(1)); 36 | mrb_define_method(mrb, foo_class, "baz", foo_bar_baz, MRB_ARGS_REQ(1)); 37 | 38 | // To get the class use: mrb_class_get_under(mrb, foo_module, "Bar"); 39 | 40 | mrb_load_irep(mrb, class_under_module_mrb); 41 | 42 | mrb_close(mrb); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /class_under_module_mrb.rb: -------------------------------------------------------------------------------- 1 | foo_bar = Foo::Bar.new('Test') 2 | foo_bar.baz('class + module') 3 | -------------------------------------------------------------------------------- /run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for bin_test in "$@" 4 | do 5 | echo -n "${bin_test}: " 6 | ./$bin_test > /tmp/$bin_test.tst 2>&1 7 | diff /tmp/$bin_test.tst test_output/$bin_test.tst > /dev/null 2>&1 8 | if [ $? -eq 0 ] 9 | then 10 | echo -e "\033[1;32m\xE2\x9c\x93\033[1;0m" 11 | else 12 | echo -e "\033[1;31m\xE2\x98\xA0\033[1;0m" 13 | echo "**************" 14 | echo "Expected: " 15 | cat test_output/$bin_test.tst 16 | echo "**************" 17 | echo "Got: " 18 | cat /tmp/$bin_test.tst 19 | echo "**************" 20 | fi 21 | rm -f /tmp/$bin_test.tst 22 | done 23 | -------------------------------------------------------------------------------- /simple_class.c: -------------------------------------------------------------------------------- 1 | #include "mruby.h" 2 | #include "mruby/irep.h" 3 | #include "mruby/string.h" 4 | 5 | #include "simple_class_mrb.h" 6 | 7 | static mrb_value foo_init(mrb_state* mrb, mrb_value self) 8 | { 9 | char *message = NULL; 10 | mrb_get_args(mrb, "z", &message); 11 | 12 | fprintf(stderr, "foo initialized with: %s\n", message); 13 | 14 | return self; 15 | } 16 | 17 | static mrb_value foo_bar(mrb_state* mrb, mrb_value obj) 18 | { 19 | char *message = NULL; 20 | mrb_get_args(mrb, "z", &message); 21 | 22 | fprintf(stderr, "bar: %s\n", message); 23 | 24 | return mrb_nil_value(); 25 | } 26 | 27 | int main(void) 28 | { 29 | mrb_state *mrb = mrb_open(); 30 | 31 | struct RClass *foo_class = mrb_define_class(mrb, "Foo", mrb->object_class); 32 | 33 | mrb_define_method(mrb, foo_class, "initialize", foo_init, MRB_ARGS_REQ(1)); 34 | mrb_define_method(mrb, foo_class, "bar", foo_bar, MRB_ARGS_REQ(1)); 35 | 36 | mrb_load_irep(mrb, simple_class_mrb); 37 | 38 | mrb_close(mrb); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /simple_class_mrb.rb: -------------------------------------------------------------------------------- 1 | a_foo = Foo.new('init value') 2 | a_foo.bar('Test message') 3 | -------------------------------------------------------------------------------- /simple_module.c: -------------------------------------------------------------------------------- 1 | #include "mruby.h" 2 | #include "mruby/irep.h" 3 | #include "mruby/string.h" 4 | 5 | #include "simple_module_mrb.h" 6 | 7 | static mrb_value foo_bar(mrb_state* mrb, mrb_value obj) 8 | { 9 | char *message = NULL; 10 | mrb_get_args(mrb, "z", &message); 11 | 12 | fprintf(stderr, "bar: %s\n", message); 13 | 14 | return mrb_nil_value(); 15 | } 16 | 17 | int main(void) 18 | { 19 | mrb_state *mrb = mrb_open(); 20 | 21 | struct RClass *foo_module = mrb_define_module(mrb, "Foo"); 22 | 23 | mrb_define_class_method(mrb, foo_module, "bar", foo_bar, MRB_ARGS_REQ(1)); 24 | 25 | mrb_load_irep(mrb, simple_module_mrb); 26 | 27 | mrb_close(mrb); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /simple_module_mrb.rb: -------------------------------------------------------------------------------- 1 | puts 'Before call' 2 | Foo.bar('Test message') 3 | puts 'After call' 4 | -------------------------------------------------------------------------------- /simple_yield.c: -------------------------------------------------------------------------------- 1 | #include "mruby.h" 2 | #include "mruby/irep.h" 3 | #include "mruby/string.h" 4 | 5 | #include "simple_yield_mrb.h" 6 | 7 | static mrb_value foo_init(mrb_state* mrb, mrb_value self) 8 | { 9 | return self; 10 | } 11 | 12 | static mrb_value foo_bar(mrb_state* mrb, mrb_value obj) 13 | { 14 | mrb_value block; 15 | mrb_get_args(mrb, "&", &block); 16 | 17 | fprintf(stderr, "Before block\n"); 18 | 19 | mrb_yield_argv(mrb, block, 0, NULL); 20 | 21 | fprintf(stderr, "After block\n"); 22 | 23 | return mrb_nil_value(); 24 | } 25 | 26 | int main(void) 27 | { 28 | mrb_state *mrb = mrb_open(); 29 | 30 | struct RClass *foo_class = mrb_define_class(mrb, "Foo", mrb->object_class); 31 | 32 | mrb_define_method(mrb, foo_class, "initialize", foo_init, MRB_ARGS_NONE()); 33 | mrb_define_method(mrb, foo_class, "bar", foo_bar, MRB_ARGS_BLOCK()); 34 | 35 | mrb_load_irep(mrb, simple_yield_mrb); 36 | 37 | mrb_close(mrb); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /simple_yield_mrb.rb: -------------------------------------------------------------------------------- 1 | foo = Foo.new 2 | foo.bar do 3 | puts "in foo.bar block" 4 | end 5 | -------------------------------------------------------------------------------- /simplest.c: -------------------------------------------------------------------------------- 1 | #include "mruby.h" 2 | #include "mruby/irep.h" 3 | 4 | #include "simplest_mrb.h" 5 | 6 | int main(void) 7 | { 8 | mrb_state *mrb = mrb_open(); 9 | 10 | mrb_load_irep(mrb, simplest_mrb); 11 | 12 | mrb_close(mrb); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /simplest_mrb.rb: -------------------------------------------------------------------------------- 1 | puts "Test" 2 | -------------------------------------------------------------------------------- /test_output/class_under_module.tst: -------------------------------------------------------------------------------- 1 | Foo::Bar initialized with: Test 2 | baz: class + module 3 | -------------------------------------------------------------------------------- /test_output/simple_class.tst: -------------------------------------------------------------------------------- 1 | foo initialized with: init value 2 | bar: Test message 3 | -------------------------------------------------------------------------------- /test_output/simple_module.tst: -------------------------------------------------------------------------------- 1 | bar: Test message 2 | Before call 3 | After call 4 | -------------------------------------------------------------------------------- /test_output/simple_yield.tst: -------------------------------------------------------------------------------- 1 | Before block 2 | After block 3 | in foo.bar block 4 | -------------------------------------------------------------------------------- /test_output/simplest.tst: -------------------------------------------------------------------------------- 1 | Test 2 | --------------------------------------------------------------------------------