I am currently working on a way to bind an Mruby interpreter to Crystal projects. However, my current code segfaults on Windows (while running perfectly on WSL Ubuntu) with the 64bit Visual Studio environment and I do not find a solution for the problem.
Everything compiles fine and the program itself works, but as soon as I execute a Ruby command, it crashes (for debug and release builds) with an access violation.
@[Link(ldflags: "#{__DIR__}/build/lib/libmruby.lib msvcrt.lib Ws2_32.lib")] # Link mruby and standard library
lib Mruby # Generate bindings
type MrbState = Void
fun mrb_open() : MrbState*
fun mrb_close(mrb : MrbState*)
fun mrb_load_string(mrb : MrbState*, s : LibC::Char*)
end
mrb = Mruby.mrb_open() # Load context, works fine
Mruby.mrb_load_string(mrb, "puts 123") # This crashes the program
Mruby.mrb_close(mrb) # Close context again, would also work fine without the line above
puts "Everything okay" # Does not show
To compile the Crystal code, I wrote a batch script:
set CRYSTAL_PATH=%CD%\third_party\crystal\src;%CD%\third_party
set PATH=%PATH%;%CD%\third_party\crystal
set LIB=%LIB%;%CD%\third_party\crystal
cd third_party/mruby
ruby minirake MRUBY_BUILD_DIR="../../build" MRUBY_CONFIG="../../mruby_build_config.rb"
cd ../..
crystal build test.cr -o test.exe
The source codes for Crystal and Mruby are in the third_party
directory, under the folders crystal
and mruby
, respectively. Links to the repos are:
https://github.com/mruby/mruby and https://github.com/crystal-lang/crystal
The Crystal binaries are obtained from the Github CI scripts for Windows and were just copied into the Crystal directory.
The config file for Mruby is simply:
MRuby::Build.new do |conf|
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
conf.gembox 'default'
conf.build_dir = ENV["MRUBY_BUILD_DIR"] || raise("MRUBY_BUILD_DIR undefined!")
end
The same program written in C does work, so the problem seems to be connected to Crystal somehow:
#include <mruby.h>
#include <mruby/compile.h>
int main() {
mrb_state* mrb = mrb_open();
mrb_load_string(mrb, "puts 123");
mrb_close(mrb);
return 0;
}
The C program was compiled using the following line:
cl main.c /I third_party/mruby/include msvcrt.lib Ws2_32.lib build/lib/libmruby.lib
I tried to debug the program with Visual Studio, but the debugger does not seem to be compatible with the Crystal-generated code. Changing compiler flags and defines did not help either.
I really have no idea where the problem is and don't know how to fix this or how to find out what causes it.