[RUBY] Rubin / Rost-Kooperation (2) Mittel

Artikelserie

Einführung

Es gibt verschiedene Ebenen und Methoden zum Verknüpfen von Ruby und Rust.

Verwenden Sie Rust-Befehle

Man kann sagen: "Was ist los?", Aber eine der Kooperationsmethoden besteht darin, das von Rust aus Ruby erstellte CLI-Tool (kurz den Befehl) aufzurufen.

Von der Ruby-Seite Kernel. # System und [IO.popen](https: // docs) Rufen Sie ein externes Programm mit .ruby-lang.org / ja / 2.7.0 / method / IO / s / popen.html auf.

Angenommen, Sie haben eine CSV mit einer großen Anzahl von Spalten und Zeilen und möchten einige der Spalten extrahieren und eine Verarbeitung wie die Aggregation durchführen. Ein von Rust erstelltes Tool namens xsv ist nützlich, um Spalten zu extrahieren.

xsv select name,phone people.csv

Wenn Sie schreiben, wird eine CSV-Datei, die nur die Namens- und Telefonspalte aus people.csv extrahiert, an die Standardausgabe gesendet. Dies ist die Vorverarbeitung.

Es spielt jedoch keine Rolle, ob es sich um Rust handelt oder nicht, wenn Sie es nur als externen Befehl aufrufen. In diesem Abschnitt wollte ich zeigen, dass "es auch eine Möglichkeit gibt, ein Programm zu kombinieren, das vollständig unabhängig durch Befehlsaufruf und Standardeingabe / -ausgabe erstellt wurde, auch wenn es als Kooperation bezeichnet wird", aber ich werde es später nicht behandeln.

FFI: Über Fremdfunktionsschnittstelle

(Hinweis: Wie bei anderen Abschnitten habe ich es geschrieben, ohne es zu verstehen, daher kann es zu Fehlern kommen.)

FFI wird auf Japanisch als "andere Sprachfunktionsschnittstelle" bezeichnet und ist einer der Mechanismen zum Aufrufen von Funktionen (usw.) zwischen verschiedenen Programmiersprachen.

Die Art der Daten, die übergeben werden können, scheint auf der der C-Sprache (?) Zu basieren, und es gibt erhebliche Einschränkungen. Wenn Sie beispielsweise Ganzzahlen austauschen, muss der Typ wie "uint8" (vorzeichenlose 8-Bit-Ganzzahl) oder "int32" (vorzeichenbehaftete 32-Bit-Ganzzahl) geklärt werden. Ganzzahlige Objekte, die nicht in diesen Bereich passen, müssen geklärt werden. Sie können es nicht übergeben. Es scheint, dass selbst Ruby-Arrays und -Hashes (zumindest leicht) nicht ausgetauscht werden können. Der Austausch von Zeichenketten ist etwas mühsam.

Ich denke, dies ist wahrscheinlich die Liste der verfügbaren Typen: Types · ffi/ffi Wiki

Das Aufrufen von Rust-Funktionen von Ruby über FFI ist nicht schwierig. Auf der Rostseite

#[no_mangle]
pub extern fn hoge(x: f64, y: f64) -> f64 {
  x + y
}

Definieren und kompilieren Sie die Funktion wie folgt.

Auf der Ruby-Seite verwenden wir einen Edelstein namens ffi. Und

require "ffi"

module Hoge
  extend FFI::Library
  ffi_lib "path/to/library/file"
  attach_function :hoge, [:double, :double], :double
end

p Hoge.hoge(2.0, 3.0) # => 5.0

Nennen wir es wie. Ist es nicht leicht genug zu schlagen?

Später werde ich einen Artikel in FFI schreiben, der Rust-Funktionen von Ruby aufruft.

Helix

Während FFI eine Allzweckspezifikation ist, die verschiedene Sprachen verbindet, dienen Helix in diesem Abschnitt und Rutie im nächsten Abschnitt nur zum Verbinden von Ruby und Rust.

Sie können die folgenden zwei auf der offiziellen Website von Helix sehen.

Auch die folgenden Artikel sind sehr nützlich.

Zusammenfassung einiger Möglichkeiten, Rust von Ruby-Qiita aus aufzurufen

Im Beispiel der offiziellen Site ist es plötzlich in das Ruby on Rails-Projekt integriert, und es ist nicht klar für diejenigen, die keine Rails machen, aber die obige Site ist ein Beispiel für die Herstellung eines Edelsteins und leicht zu verstehen.

Helix ist erstaunlich, dass Sie mit Rust Ruby-Klassen erstellen können. Sind Sie im Ernst.

Auf der Rostseite wird eine Kiste namens Helix verwendet. Dann können Sie das Makro "Ruby!" Verwenden

ruby! {
  class Hoge {
    //Instanzmethode
    def foo(&self, s: String) {
    
    }
    
    //Klassenmethode
    def bar(s: String) {
    
    }
  }
}

Es scheint, dass Sie so schreiben können. Im Gegensatz zu FFI ist der Austausch von Zeichenketten so einfach wie oben.

Interessant ist, dass Rubys Werte "String object or nil" und "Float object or nil "als RustsOption <String>undOption <f64>ausgetauscht werden können (ich weiß nicht). ).

Arrays und Hashes können nicht ausgetauscht werden. Laut Roadmap langfristige Ziele

Ist oben.

Ein wenig enttäuschend ist, dass die Entwicklung (für das Auge) langsam zu sein scheint. Stand: 4. September 2020

Es ist geworden. Es ist auch schwer zu sagen, dass die Wartung der Website ausreichend ist.

Ich habe Helix noch nicht ausprobiert, möchte aber etwas mehr recherchieren und einen Artikel schreiben.

Rutie

Rutie scheint wie "rooty" ausgesprochen zu werden. Es scheint ein impliziter Name zu sein, wie z. B. Krawatte (Krawatte) Ru of Ruby und Ru of Rust. Offizielle Seite hier:

Wie Helix kann Rust Ruby-Klassen erstellen. Sie können auch Module erstellen. Auf der Rostseite wird eine Kiste namens Rutie verwendet. Zum Beispiel

module!(Hoge);

mehtods!(
    Hoge,
    _rtself,
    
    fn foo(s: RString) -> RString {
        //Und so weiter
    }
);

Es scheint, dass Sie das "Hoge" -Modul und seine singuläre Methode "foo" definieren können. (Auf der Rost-Seite ist etwas mehr Beschreibung erforderlich, um dies in Ruby verfügbar zu machen.)

Auf der Rubinseite verwenden wir einen Edelstein namens Rutie (gleicher Name wie die Kiste). Das Codebeispiel auf der Ruby-Seite wird weggelassen. Ich habe vor, später einen weiteren Artikel zu schreiben.

In Rutie können Sie auch Ruby-Methoden auf der Rust-Seite verwenden. Das ist interessant. Ich habe es jedoch noch nicht ausprobiert, daher bin ich mir nicht sicher, was es ist.

Die neueste Version von Rutie am 4. September 2020 ist Juli 2020 (Version 0.8.0).

Andere

Es gibt verschiedene andere Mittel.

Schon erwähnt

Zusammenfassung einiger Möglichkeiten, Rust von Ruby-Qiita aus aufzurufen

Beschreibt auch die Methode mit WASM (WebAssembly).

Übrigens gab es viele Einschränkungen hinsichtlich der Datentypen, die ausgetauscht werden konnten, egal ob es sich um FFI, Helix oder Rutie handelte.

Ist die Methode über Apache Arrow auch für den Austausch großer Datenmengen vielversprechend? Der Autor hat keine Ahnung davon. Ruby und Rust verfügen jedoch über Bibliotheken, die Arrow verwenden.

Wenn die Daten eine komplizierte Struktur haben und Sie sich nicht für die Kodierungs- / Dekodierungszeit interessieren, kann dies über JSON oder MessagePack erfolgen. Sowohl JSON als auch MessagePack sind mit Ruby und Rust einfach zu verwenden.

Benchmark-Test (hinzugefügt am 18.09.2020)

Ich habe die Geschwindigkeit jeder Methode nicht selbst verglichen, aber ich habe eine Benchmark-Teststelle gefunden. https://github.com/bbugh/ruby-rust-extension-benchmark (Oktober 2019)

Helix scheint in diesem Benchmark-Test langsamer zu sein als Rutie. Die Kosten für die Interaktion zwischen Ruby / Rust können etwas hoch sein.

Benchmark-Tests ändern häufig ihre Rangfolge mit nur geringfügigen Änderungen in Inhalt und Umfang, und es kann gefährlich sein, eine Entscheidung allein aufgrund der oben genannten Tests zu treffen. Angesichts der Funktionalität und des Entwicklungstempos bin ich jedoch der Meinung, dass Rutie derzeit diejenige ist, wenn nur eine davon untersucht und verwendet wird.

Recommended Posts

Rubin / Rost-Kooperation (2) Mittel
Rubin / Rost-Zusammenarbeit (1) Zweck
Rubin / Rost-Kooperation (6) Extraktion der Morphologie
Ruby / Rust-Verknüpfung (4) Numerische Berechnung mit Rutie