[英]Is it possible / easy to include some mruby in a nim application?
我現在正在努力學習Nim(它正在慢慢進行 - 不能投入太多時間)。 另一方面,為了獲得一些正常工作的代碼,我想將我正在研究的Nim應用程序的部分原型化為ruby。
由於mruby允許在C app中嵌入ruby子集,並且由於nim允許將任意C代碼編譯為函數,因此感覺這應該相對簡單。 有人這樣做過嗎?
我特別想找到使用Nim的時髦宏功能來突破內聯ruby代碼的方法。 我將嘗試自己,但我認為有人必須嘗試它和/或提出比我目前的學習狀態更優雅的解決方案:)
https://github.com/micklat/NimBorg
這是一個目標有些類似的項目。 它目前以python和lua為目標,但使用相同的技術與Ruby接口應該不會太難。
Nim中有幾個功能可以幫助以流暢的方式與外語連接:
1)使用Nim的點運算符從Nim調用Ruby
這些有點像Ruby中的method_missing
。 您可以在Nim中定義類似RubyValue
的類型,它將具有點運算符,可將任何表達式(如foo.bar
或foo.bar(baz)
轉換為適當的Ruby方法調用。 參數可以傳遞給類似toRubyValue
的泛型函數,可以為各種Nim和C類型重載,以自動將它們轉換為正確的Ruby類型。
2)從Ruby調用Nim
在大多數腳本語言中,有一種方法可以注冊外部類型,通常在每個導出類型必須填充一次的特定數據結構中描述。 您可以使用一些通用編程和Nim的.global.
vars為通過點運算符傳遞給Ruby的每種類型自動創建和緩存所需的數據結構。 將會有一個像getRubyTypeDesc(T: typedesc)
這樣的通用proc,它可能依賴於typeinfo
, typetraits
或用戶提供的一些重載過程,定義了必須為該類型導出的內容。
現在,如果你真的想依賴mruby(因為你有經驗),你可以考慮使用.emit。 pragma直接輸出mruby代碼片段。 然后,您可以要求Nim編譯器僅生成源代碼 ,您將在第二步中編譯,或者您只需更改編譯器可執行文件,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因為,出於某種原因,clang似乎認為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,但這已經完成了我現在所需要的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.