1

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

ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();

足以让我使用基本的 VM 和内置类运行。但是,我还将标准库与我的应用程序打包在一起,因为我打算从我的应用程序中使用 FileUtils 和 Resolv 等工具。我可以require并且很好地使用一些库,但是当我require '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");

这清除了先前的错误,但给我留下了code converter not found (UTF-8 to UTF-16LE). 这可以通过添加一行来解决rb_eval_string("require 'enc/trans/transdb'");,但是,我不想逐个复制 rubyruby_options​​ 函数执行的初始化代码,所以我尝试直接使用它,就像在 ruby​​ 自己的main函数中一样......

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 scripts/bootstrap.rb. 似乎 ruby​​ 忽略了我的参数ruby_options并使用系统提供的 argc 和 argv 值(显然在 Windows 上这种情况已经有一段时间了)。这很麻烦,因为我希望我的应用程序只需双击可执行文件即可运行,并且不需要用户提供指示“引导”脚本位置的命令行参数。

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

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

4

1 回答 1

0

我在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 文件中搜索符号,我能够Init_encdb在 encdb.so 和Init_transdbtrans/transdb.so 中找到。所以,我需要这些库和我的引导脚本,如下所示:

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_index("encdb");散布到我的初始化代码中,那么这似乎是合理的。

我仍然对任何更简单的替代方案感兴趣,并且会推迟接受这个作为答案 - 至少有一段时间 - 直到我收到一些确认我正在正确地解决这个问题。

于 2014-08-22T16:17:43.007 回答