استفاده از Rust در nodejs با FFI

سلام گاهی پیش میاد که نیاز داشته باشید از زبان های دیگه در برنامه استفاده کنید. تو این پست میخوام یه مقدمه از ffi (foreign function interface) در nodejs ارایٔه دهم.FFI یعنی چی؟به‌طور کلی، FFI مکانیزمی است که به وسیله آن برنامه‌ای که با یک زبان برنامه‌نویسی نوشته شده است، می‌تواند از روتین‌ها و خدماتی که با زبان دیگری نوشته یا کامپایل شده‌اند، استفاده کند.می‌توانید از تعریف ویکی‌پدیا برای این موضوع استفاده کنید:A foreign function interface (FFI) is a mechanism by which a program written in one programming language can call routines or make use of services written or compiled in another one.(wikipedia :منبع)مثالی از استفاده از FFI در Node.js و Rustفرض کنید یک عملیات سنگین را نیاز دارید که بهتر است از زبان Rust به جای Node.js استفاده کنید تا بهبود عملکرد برنامه‌تان را تجربه کنید. به عنوان مثال، فرض کنید محاسبه‌ی دنباله فیبوناچی را با استفاده از Rust انجام داده و خروجی را در Node.js دریافت کنید.اجازه دهید با یک مثال این موضوع را بهتر درک کنید. در محیط ترمینال دستورات زیر را وارد کنید:$ mkdir my_ffi $ cd my_ffi $ cargo new rust_app # ساخت پروژه با rust $ cd rust_app $ mkdir ./src/math $ touch lib.rsتا اینجا، یک دایرکتوری به نام my_ffi ساخته شده است و داخل آن یک پروژه Rust با دستور cargo new rust_app ساخته شده است. سپس، یک ماژول به نام math در مسیر src/math ایجاد شده است. همچنین، نیاز است که در فایل Cargo.toml تعریف کنیم که این ماژول مورد استفاده قرار بگیرد.[package] name = &quotrust_app&quot version = &quot0.1.0&quot edition = &quot2021&quot # این چهار خط را اضافه کنید [lib] name = &quotmath&quot path = &quot./src/math/lib.rs&quot crate-type=[&quotrlib&quot,&quotcdylib&quot] [dependencies]مرحله تعریف ماژول به پایان رسید. اما نیاز است که توضیحی کوچک درباره crate-type = ["rlib", "cdylib"] بدهم.خلاصه‌اش این است که این خط نوع کتابخانه تولید شده را تعیین می‌کند. rlib به معنی این است که یک کتابخانه Rust استاتیک تولید شده است و cdylib به معنی این است که یک کتابخانه Rust پویا است و می‌توانید از آن در زبان‌هایی مانند C، C#، Java، JavaScript و غیره استفاده کنید. برای درک بهتر، لینک مرجع را مطالعه کنید.حالا نوبت به فایل src/math/lib.rs می‌رسد. کد زیر را بنویسید:#[no_mangle] pub extern &quotC&quot fn fib(number: i32) -> i32 { if number == 0 { return 0; } else if number == 1 { return 1; } else { return fib(number - 1) + fib(number - 2); } }در این قسمت، تابع محاسبه‌ی دنباله فیبوناچی را نوشته‌ایم. قبل از ادامه، توضیح کوچکی درباره برخی کلمات کلیدی در کد ضروری است.pub: به این معنی است که از این تابع می‌توان در ماژول‌های دیگر استفاده کرد.extern: این کلیدواژه به این معنی است که می‌توان از این تابع در خارج از برنامه نیز استفاده کرد.#[no_mangle]: به طور کلی به کامپایلر Rust می‌گوید نام این تابع را تغییر ندهد.حالا کدهای Rust به پایان رسیده‌اند و در نهایتنیاز است که یک نسخه‌ی Release از آن بسازیم. برای این کار، دستور زیر را در ترمینال اجرا کنید:$ cargo build --releaseدر نهایت، یک فایل Release در دایرکتوری target ساخته شده است.حالا به بخش Node.js می‌رویم. دستورات زیر را برای ساخت یک پروژه Node.js وارد ترمینال کنید:$ cd .. $ mkdir node_app $ cd node_app $ npm init -y $ npm i ffi-napi # نصب ffi-napi $ touch index.js # ساخت فایل index.jsسپس، در فایل package.json، قسمت scripts را به صورت زیر ویرایش کنید:&quotscripts&quot: { &quotstart&quot: &quotnode index.js&quot }در انتها، کد JavaScript را بنویسید و از Rust استفاده کنید:const ffi = require(&quotffi-napi&quot); // مسیر لایبری که میخوایم استفاده کینم // نیازی به وارد کردن پسوند نیست const libPath = &quot../rust_app/target/release/libmath" const math = ffi.Library(path, { // <function_name>: [ &quot<return_value_type>&quot: [&quot<argType>&quot] ] fib: [&quotint&quot, [&quotint&quot]], }); const result = math.fib(45); console.log(result);و تمام!