我目前正在努力学习Nim(它正在慢慢地发展 - 不能投入太多时间)。另一方面,为了获得一些工作代码,我想用Ruby创建一个Nim应用程序的部分原型。在nim应用程序中包含mruby是否可能/容易?
由于mruby允许在C应用程序中嵌入ruby子集,并且由于nim允许将任意C代码编译为函数,所以感觉这应该是相对直接的。有人做过这个吗?
我特别寻找使用Nim的时髦宏特性打破内联ruby代码的方法。我要去尝试我自己,但我想有人会尝试它和/或想出更优雅的解决方案比我在我目前的学习:)的状态
我目前正在努力学习Nim(它正在慢慢地发展 - 不能投入太多时间)。另一方面,为了获得一些工作代码,我想用Ruby创建一个Nim应用程序的部分原型。在nim应用程序中包含mruby是否可能/容易?
由于mruby允许在C应用程序中嵌入ruby子集,并且由于nim允许将任意C代码编译为函数,所以感觉这应该是相对直接的。有人做过这个吗?
我特别寻找使用Nim的时髦宏特性打破内联ruby代码的方法。我要去尝试我自己,但我想有人会尝试它和/或想出更优雅的解决方案比我在我目前的学习:)的状态
https://github.com/micklat/NimBorg
这是一个项目的目标有点类似。它目前的目标是python和lua,但使用相同的技术来与Ruby进行交互应该不会太难。
有位于稔几个特点,在流畅的方式与外国语言接口帮助:使用
1)拨打国际长途稔红宝石尼姆dot operators
这是一个有点像红宝石method_missing
。 您可以在Nim中定义类似RubyValue
的类型,该类型将具有点运算符,可将foo.bar
或foo.bar(baz)
之类的表达式转换为适当的Ruby方法调用。这些参数可以传递给像toRubyValue
这样的泛型函数,它们可以被各种Nim和C类型重载,以便自动将它们转换为右侧的Ruby类型。
2)从红宝石
在大多数脚本语言调用稔,有注册一个外国的类型,常常在具有要填充每导出的类型一旦特定数据结构所描述的方法。您可以使用一些通用编程和Nim的变量来自动创建并缓存通过点运算符传递给Ruby的每种类型所需的数据结构。将会有一个像getRubyTypeDesc(T: typedesc)
这样的通用proc,它可能依赖于typeinfo
,typetraits
或用户提供的某些重载的特效,定义必须为该类型导出的内容。
现在,如果你真的想依靠mruby(因为你有它的经验),你可以看看使用.emit. pragma直接输出mruby代码块。然后,您可以要求Nim编译器generate only source code,您将在第二步中编译,或者您可以更改编译该项目时Nim将调用的编译器可执行文件(这在上面链接的相同部分进行了说明)。
这是我到目前为止发现的。
从mruby执行中获取返回值并不像我想象的那么容易。这就是说,大量的试验和错误之后,这是我发现得到一些mruby代码来执行的最简单的方法:
const mrb_cc_flags = "-v -I/mruby_1.2.0_path/include/ -L/mruby_1.2.0_path/build/host/lib/"
const mrb_linker_flags = "-v"
const mrb_obj = "/mruby_1.2.0_path/build/host/lib/libmruby.a"
{. passC: mrb_cc_flags, passL: mrb_linker_flags, link: mrb_obj .}
{.emit: """
#include <mruby.h>
#include <mruby/string.h>
""".}
proc ruby_raw(str:cstring):cstring =
{.emit: """
mrb_state *mrb = mrb_open();
if (!mrb) { printf("ERROR: couldn't init mruby\n"); exit(0); }
mrb_load_string(mrb, `str`);
`result` = mrb_str_to_cstr(mrb, mrb_funcall(mrb, mrb_top_self(mrb), "test_func", 0));
mrb_close(mrb);
""".}
proc ruby*(str:string):string =
echo ruby_raw("def test_func\n" & str & "\nend")
"done"
let resp = ruby """
puts 'this was a puts from within ruby'
"this is the response"
"""
echo(resp)
我敢肯定,你应该能够省略一些编译器标志在配置良好的环境中的文件开始处,例如,通过正确设置LD_LIBRARY_PATH(并非最不重要的,因为这会使代码的可移植性)
一些到目前为止,我所遇到的问题:
我被迫mrb_funcall使用,因为,出于某种原因,铛似乎认为mrb_load_string函数返回一个int
,尽管所有的C代码我能找到和文档和几个人在网上说,否则:
error: initializing 'mrb_value' (aka 'struct mrb_value') with an expression of incompatible type 'int'
mrb_value mrb_out = mrb_load_string(mrb, str);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~
的mruby/string.h中头球需要mrb_str_to_cstr
,否则你会遇到段错误。 RSTRING_PTR似乎也可以正常工作(至少在没有string.h的情况下提供了一个明智的错误),但是如果将它作为上面的单线程写入,它将执行两次函数。
我打算继续写一些稍微习惯的nim,但是这已经完成了我现在需要的。
哇,一些优秀的指针在那里,谢谢! – user208769