Présentation de «Introduction à la programmation pratique de Rust» (jour 4) Appel de Rust depuis Ruby

Aperçu

"Introduction à la programmation pratique de Rust" Reportez-vous aux pages 421-427 et appelez les fonctions Rust de Ruby. À propos, aujourd'hui (vendredi 4 septembre 2020) c'est Ruby Kaigi.

Préparation pour Windows

Téléchargez Ruby pour Windows depuis RubyInstaller pour Windows. Au moment de la rédaction de cet article, le dernier est [Ruby + Devkit 2.7.1-1 (x64)](https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-2.7.1-1/rubyinstaller-devkit-2.7. 1-1-x64.exe).

01_RubyInstaller2_01.png

Il y a "En cas de doute, appuyez sur ENTER", appuyez donc sur ENTER pour continuer.

02_RubyInstaller2_02.png

Puisqu'il dit "Installation réussie de la chaîne d'outils de développement MSYS2 et MINGW", ENTER était-il identique à appuyer sur 3? Appuyez maintenant sur ENTRÉE pour terminer l'installation.

Vérifiez le fonctionnement de ruby sur Windows PowerShell.

PS > ruby -v
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x64-mingw32]

Vous pouvez le vérifier avec VS Code en rouvrant TERMINAL.

p.421 Exemple: appeler une fonction Rust depuis Ruby.

Créez un répertoire de projet pour mener les expériences en p.421.

PS > cargo new ffitest
     Created binary (application) `ffitest` package

Créez un exemple de répertoire sous ffitest, écrivez du code Ruby et testez le traitement Ruby.

ffitest/sample/add_array.rb


def add_array(n,x)
    a = Array.new(n,0)
    x.times do
        for i in 0..x-1
            a[i] += 1
        end
    end
    a.sum
end

puts add_array(ARGV[0].to_i, ARGV[1].to_i)

Measure-Command équivaut à «time» sous Linux commander.

PS ffitest\sample> Measure-Command {ruby add_array.rb 10000 10000}       


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 8
Milliseconds      : 53
Ticks             : 80530169
TotalDays         : 9.32062141203704E-05
TotalHours        : 0.00223694913888889
TotalMinutes      : 0.134216948333333
TotalSeconds      : 8.0530169
TotalMilliseconds : 8053.0169

À partir de TotalSeconds, vous pouvez voir que cela prend environ 8 secondes.

Vient ensuite le côté Rust. Renommez src / main.rs en src / add_array.rs.

src/add_array.rs


fn add_array(n: u64, x: u64) -> u64 {
    let mut a = vec![0u64; n as usize];
    for _ in 0..x {
        for i in 0..n as usize {
            a[i] += 1;
        }
    }
    a.iter().sum()
}

use std::env;
fn main() {
    let args: Vec<_> = env::args().collect();
    let n = args[1].parse::<u64>().unwrap();
    let x = args[2].parse::<u64>().unwrap();
    println!("{}", add_array(n, x));
}

Ajoutez le paramètre d'exécution de add_array à Cargo.toml.

Cargo.toml


[[bin]]
name = "add_array"
path = "src/add_array.rs"

p.422 Vérifiez la construction et l'exécution en bas.

PS ffitest> cargo build --release
   Compiling ffitest v0.1.0 (ffitest)
    Finished release [optimized] target(s) in 1.29s     
PS ffitest> Measure-Command {./target/release/add_array 10000 10000}     


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 93
Ticks             : 935455
TotalDays         : 1.0827025462963E-06
TotalHours        : 2.59848611111111E-05
TotalMinutes      : 0.00155909166666667
TotalSeconds      : 0.0935455
TotalMilliseconds : 93.5455

0,09 seconde. C'est vraiment rapide.

p.423 Bibliothèque

Créez un répertoire de projet pour la bibliothèque.

PS > cargo new --lib addarray
     Created library `addarray` package

[Spécification de la bibliothèque dynamique] dans Cargo.toml (https://doc.rust-lang.org/edition-guide/rust-2018/platform-and-target-support/cdylib-crates-for-c-interoperability.html )Je fais.

addarray/Cargo.toml


[lib]
crate-type = ["cdylib"]

Par le travail jusqu'à présent, src / lib.rs a été créé. Le contenu est le suivant.

src/lib.rs


#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}

Effacez le code ci-dessus et écrivez-le selon la deuxième lib.rs de la p.424.

src/lib.rs


#[no_mangle]
pub extern "C" fn add_array(n: u64, x: u64) -> u64 {
    let mut a = vec![0u64; n as usize];
    for _ in 0..x {
        for i in 0..n as usize {
            a[i] += 1;
        }
    }
    a.iter().sum()
}

Construire. En raison de diverses pensées et erreurs, si --target = x86_64-pc-windows-msvc est défini, il semble que ce sera une DLL qui peut être exécutée avec ce Ruby (recherche insuffisante).

PS > cargo build --release --target=x86_64-pc-windows-msvc       
   Compiling addarray v0.1.0 (addarray)
    Finished release [optimized] target(s) in 0.87s   

Vérifiez la bibliothèque créée.

PS addarray> ls .\target\x86_64-pc-windows-msvc\release\


annuaire: addarray\target\x86_64-pc-windows-msvc\release


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2020/09/04     --:--                .fingerprint
d-----       2020/09/04     --:--                build
d-----       2020/09/04     --:--                deps
d-----       2020/09/04     --:--                examples
d-----       2020/09/04     --:--                incremental
-a----       2020/09/04     --:--              0 .cargo-lock
-a----       2020/09/04     --:--            109 addarray.d
-a----       2020/09/04     --:--         128512 addarray.dll
-a----       2020/09/04     --:--            980 addarray.dll.exp
-a----       2020/09/04     --:--           1942 addarray.dll.lib
-a----       2020/09/04     --:--         937984 addarray.pdb

OK si addarray.dll est créé.

p.425 Appel de Ruby

Installez Ruby ffi.

PS > gem install ffi
Fetching ffi-1.13.1-x64-mingw32.gem
Successfully installed ffi-1.13.1-x64-mingw32
Parsing documentation for ffi-1.13.1-x64-mingw32
Installing ri documentation for ffi-1.13.1-x64-mingw32
Done installing documentation for ffi after 1 seconds
1 gem installed

Le code source Ruby est créé en tant que addarray / sample / add_array_rs.rb. Soyez prudent lorsque vous spécifiez le chemin de la DLL. J'étais accro à la spécification d'un chemin relatif, alors j'ai spécifié un chemin absolu.

addarray/sample/add_array_rs.rb


require 'ffi'

module AddArray
    extend FFI::Library
    ffi_lib 'C:\your\path\addarray\target\x86_64-pc-windows-msvc\release\addarray.dll'
    attach_function :add_array, [:uint64, :uint64], :uint64
end

puts AddArray::add_array(ARGV[0].to_i, ARGV[1].to_i)

p.426 Confirmation d'exécution

PS addarray\sample> Measure-Command {ruby .\add_array_rs.rb 10000 10000} 


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 311
Ticks             : 3111198
TotalDays         : 3.60092361111111E-06
TotalHours        : 8.64221666666667E-05
TotalMinutes      : 0.00518533
TotalSeconds      : 0.3111198
TotalMilliseconds : 311.1198

0,3 seconde. C'est plus lent que 0,09 seconde, mais c'était à l'origine 8 secondes, donc c'est une grande amélioration.

Extra: Paramètres d'environnement pour l'intégration Ruby & Rust pour Windows

Lorsqu'il est exécuté sous Windows, Rust doit créer une DLL appropriée en fonction de l'environnement Ruby. J'étais accro à l'écueil et j'ai enquêté sur des notes diverses.

Lors de l'ajout d'une cible de MINGW64.

PS > rustup target add x86_64-pc-windows-gnu
info: downloading component 'rust-std' for 'x86_64-pc-windows-gnu'
info: installing component 'rust-std' for 'x86_64-pc-windows-gnu'
info: Defaulting to 500.0 MiB unpack ram
 14.1 MiB /  14.1 MiB (100 %)  10.9 MiB/s in  1s ETA:  0s

Utilisez rustup pour voir la liste des cibles.

PS addarray> rustup show
Default host: x86_64-pc-windows-msvc
rustup home:  .rustup

installed targets for active toolchain
--------------------------------------

i686-pc-windows-gnu
x86_64-pc-windows-gnu
x86_64-pc-windows-msvc

active toolchain
----------------

stable-x86_64-pc-windows-msvc (default)
rustc 1.45.2 (d3fb005a3 2020-07-31)

Quand j'ai fait cargo build, j'étais en colère de ne pas pouvoir trouver x86_64-w64-mingw32-gcc. Ajoutez PATH.

PS > $ENV:Path="C:\Ruby27-x64\msys64\mingw64\bin;"+$ENV:Path

Construire.

PS addarray> cargo build --release --target=x86_64-pc-windows-gnu --verbose
       Fresh addarray v0.1.0 (addarray)
    Finished release [optimized] target(s) in 0.02s

addarray.dll est créé.

PS addarray> ls .\target\x86_64-pc-windows-gnu\release


annuaire: addarray\target\x86_64-pc-windows-gnu\release


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2020/09/04     --:--                .fingerprint
d-----       2020/09/04     --:--                build
d-----       2020/09/04     --:--                deps
d-----       2020/09/04     --:--                examples
d-----       2020/09/04     --:--                incremental
-a----       2020/09/04     --:--              0 .cargo-lock
-a----       2020/09/04     --:--            108 addarray.d
-a----       2020/09/04     --:--        3689956 addarray.dll
-a----       2020/09/04     --:--           2056 libaddarray.dll.a

add_array_rs.rb Modification et vérification du fonctionnement

Modifiez à nouveau la spécification DLL dans le code Ruby.

add_array_rs.rb


require 'ffi'

module AddArray
    extend FFI::Library
    ffi_lib 'C:\your\path\addarray\target\x86_64-pc-windows-gnu\release\addarray.dll'
    attach_function :add_array, [:uint64, :uint64], :uint64
end

puts AddArray::add_array(ARGV[0].to_i, ARGV[1].to_i)

Réflexion

  1. Lorsque vous testez Windows, faites attention à l'environnement d'exécution. Il existe divers pièges tels que mingw, 32 bits, 64 bits, etc.

Recommended Posts

Présentation de «Introduction à la programmation pratique de Rust» (jour 4) Appel de Rust depuis Ruby
Présentation de «Introduction à la programmation pratique de la rouille» (jour 3)
Introduction à la programmation pratique
Commençons par la programmation parallèle
Comment démarrer avec Slim
Introduction à Ruby (à partir d'autres langues)
J'ai essayé de démarrer avec Web Assembly
[Note] Comment démarrer avec Rspec
La programmation de jeux Ruby a commencé avec un navigateur: Introduction à Nyle-canvas (style DXRuby)
Introduction à Ruby 2
Comment démarrer avec Eclipse Micro Profile
Essayez d'obtenir la clé API de redmine avec ruby
Les débutants de Rails ont essayé de se lancer avec RSpec
Introduction à la programmation pour les étudiants du collégial (mise à jour de temps à autre)
J'ai essayé de démarrer avec Spring Data JPA
Comment obtenir JDK etc. depuis Oracle avec CLI
Premiers pas avec Ruby
De Java à Ruby !!
Commencez avec Gradle
Il est maintenant temps de commencer avec l'API Stream
Comment démarrer avec JDBC en utilisant PostgresSQL sur MacOS
J'ai essayé de démarrer avec Swagger en utilisant Spring Boot
Démarrez avec Spring Boot
Premiers pas avec les modules Ruby
[ruby] Appel d'une méthode avec un argument
Revue de code facile pour démarrer avec Jenkins / SonarQube: analyse statique
Comment obtenir et ajouter des données depuis Firebase Firestore dans Ruby