Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C++应用程序中完全初始化嵌入式Ruby VM?_Ruby_Embedded Ruby_Ruby C Extension - Fatal编程技术网

如何在C++应用程序中完全初始化嵌入式Ruby VM?

如何在C++应用程序中完全初始化嵌入式Ruby VM?,ruby,embedded-ruby,ruby-c-extension,Ruby,Embedded Ruby,Ruby C Extension,我正在将ruby版本2.1.2嵌入到wxWidgets应用程序中,在Windows上编译并瞄准Windows。链接到msvcrt-ruby210.dll并调用 ruby_sysinit(&argc, &argv); RUBY_INIT_STACK; ruby_init(); ruby_init_loadpath(); 足够让我运行基本的VM和内置类了。但是,我也将标准库与我的应用程序打包在一起,因为我打算从我的应用程序中使用FileUtils和Resolv等工具。我可以要求并使

我正在将ruby版本2.1.2嵌入到wxWidgets应用程序中,在Windows上编译并瞄准Windows。链接到msvcrt-ruby210.dll并调用

ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();
足够让我运行基本的VM和内置类了。但是,我也将标准库与我的应用程序打包在一起,因为我打算从我的应用程序中使用FileUtils和Resolv等工具。我可以要求并使用一些库,但当我需要“resolv”时,我会得到一个错误报告unitialized constant Encoding::UTF_16LE。在ruby.c中进行了一些谷歌搜索和挖掘之后,我发现我可以用以下初始化代码解决这个问题

ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();
rb_enc_find_index("encdb");
这清除了前面的错误,但留给我的是未找到UTF-8到UTF-16LE的代码转换器。通过添加额外的行rb_eval_stringrequire'enc/trans/transdb';,可以解决此问题;,但是,我并不想一块一块地复制ruby的ruby_options函数执行的初始化代码,所以我尝试直接使用它,就像在ruby自己的主函数中一样

int my_argc = 2;
char* arg1 = "myapp.exe";
char* arg2 = "scripts/bootstrap.rb";
char** my_argv = new char*[2]{arg1, arg2};

ruby_sysinit(&my_argc, &my_argv);
RUBY_INIT_STACK;
ruby_init();
ruby_run_node(ruby_options(my_argc, my_argv));
但是,这只有在使用myapp.exe脚本/bootstrap.rb运行应用程序时才有效。ruby似乎忽略了我对ruby_选项的参数,并使用了系统提供的argc和argv值。这很麻烦,因为我希望我的应用程序只需双击可执行文件即可运行,而不需要用户提供指示引导脚本位置的命令行参数

那么,在这种情况下,是否有一个方便的API或一些咒语可以用来初始化ruby而不需要命令行参数


请注意,如果可能的话,我希望避免将我的应用程序打包为ruby扩展。

我在pepper_main.c中注意到这段代码,并怀疑这正是我想要的

static VALUE
init_libraries_internal(VALUE unused)
{
  extern void Init_enc();
  extern void Init_ext();

  init_loadpath();
  Init_enc();
  Init_ext();
  return Qnil;
}
据我所知,我不需要Init_ext,因为我使用的是ruby dll,并且我不是静态编译我的扩展。因此,我尝试只使用Init_enc。虽然此符号存在于msvcrt-ruby210.dll中,但它不存在于导入库msvcrt-ruby210.dll.a中,因此我无法将其与我的应用程序链接。通过搜索lib\ruby\2.1.0\i386-mingw32\enc目录下.so文件中的符号,我能够在encdb.so中找到Init_encdb,在trans/transdb.so中找到Init_transdb。因此,我需要这些LIB和引导脚本,如下所示:

ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();
rb_require("enc/encdb");
rb_require("enc/trans/transdb");
rb_require("./scripts/bootstrap");
这使我能够无误地使用FileUtils和Resolv库。虽然我不能确定我不会遇到更多像这样的问题,但我还没有尝试需要一个真正的宝石。。。这是一个我比较满意的解决方案。如果我能用一个简单的需求解决任何即将出现的问题,而不是到处寻找诸如rb_enc_find_indexencdb之类的晦涩命令;在我的初始化代码中加入,这似乎是合理的


我仍然对任何更简单的替代方案感兴趣,并将暂缓接受这一答案——至少在一段时间内——直到我得到一些确认,证明我的做法是正确的。

事实证明,这种方法确实相当有效。在使用RubyInstaller配方构建ruby之后,我能够以这种方式加载ruby,并且一切正常。我甚至可以在需要rubygems(包括pg和sequel)后加载rubygems。看起来这很好。