العمل مع WebAssembly وJavaScript: من الألف إلى الياء في Node.js

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة عن WebAssembly ودوره في Node.js

\n\n

WebAssembly (WASM) هو تنسيق تعليمات ثنائي منخفض المستوى يتم تنفيذه في آلة افتراضية بأداء شبه أصلي. في نظام Node.js البيئي، يفتح WebAssembly آفاقًا جديدة: فهو يسمح بتنفيذ كود مكتوب بلغات C أو C++ أو Rust أو Go مباشرة في بيئة الخادم. هذا مهم بشكل خاص للمهام التي تتطلب أداءً عاليًا: معالجة الصور، التشفير، تحليل البيانات، العمل مع مصفوفات كبيرة من الأرقام.

\n\n

في هذه المقالة، سنستعرض دورة العمل الكاملة مع WebAssembly في Node.js: من ترجمة الكود المصدر إلى دمج الوحدة الجاهزة في تطبيق JavaScript.

\n\n

المفاهيم الأساسية وإعداد البيئة

\n\n

ما تحتاج معرفته قبل البدء

\n

وحدة WebAssembly هي ملف ثنائي بامتداد .wasm. لا يمكنها الوصول مباشرة إلى DOM أو نظام الملفات — كل التفاعل يتم من خلال "دوال مستوردة" تمررها من JavaScript. في Node.js، يتم إزالة هذا القيد باستخدام أغلفة خاصة.

\n\n

تثبيت الأدوات

\n

لترجمة الكود إلى WASM، نحتاج إلى Emscripten SDK. التثبيت على Linux/macOS:

\n
git clone https://github.com/emscripten-core/emsdk.git\ncd emsdk\n./emsdk install latest\n./emsdk activate latest\nsource ./emsdk_env.sh
\n\n

لمشاريع Rust، استخدم wasm-pack:

\n
npm install -g wasm-pack
\n\n

إنشاء وترجمة أول وحدة WASM

\n\n

مثال بلغة C — دالة الجمع

\n

لننشئ دالة بسيطة بلغة C تجمع رقمين:

\n
// math.c\n#include <emscripten.h>\n\nEMSCRIPTEN_KEEPALIVE\nint add(int a, int b) {\n    return a + b;\n}\n\nEMSCRIPTEN_KEEPALIVE\nint multiply(int a, int b) {\n    return a * b;\n}
\n\n

نقوم بترجمتها إلى WASM باستخدام Emscripten:

\n
emcc math.c -o math.js -s EXPORTED_FUNCTIONS="['_add', '_multiply']" -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME="createMathModule"
\n\n

نحصل على ملفين: math.wasm و math.js — وهو غلاف للتحميل.

\n\n

تحميل الوحدة في Node.js

\n

الآن نستخدم الوحدة في JavaScript:

\n
// index.js\nconst createMathModule = require('./math.js');\n\ncreateMathModule().then(module => {\n    const add = module._add;\n    const multiply = module._multiply;\n\n    console.log('5 + 3 =', add(5, 3));        // 8\n    console.log('4 * 7 =', multiply(4, 7));  // 28\n});
\n\n

نقوم بتشغيله:

\n
node index.js
\n\n

العمل مع الذاكرة وأنواع البيانات المعقدة

\n\n

تمرير السلاسل والمصفوفات

\n

WASM يتعامل فقط مع الأرقام. لتمرير السلاسل أو المصفوفات، يجب تخصيص ذاكرة في الذاكرة الخطية للوحدة. لنلق نظرة على مثال بلغة C يقبل سلسلة ويعيد طولها:

\n
// string_ops.c\n#include <string.h>\n#include <emscripten.h>\n\nEMSCRIPTEN_KEEPALIVE\nint string_length(char* str) {\n    return strlen(str);\n}\n\nEMSCRIPTEN_KEEPALIVE\nvoid to_upper(char* str) {\n    for (int i = 0; str[i]; i++) {\n        if (str[i] >= 'a' && str[i] <= 'z') {\n            str[i] -= 32;\n        }\n    }\n}
\n\n

نقوم بترجمته:

\n
emcc string_ops.c -o string_ops.js -s EXPORTED_FUNCTIONS="['_string_length', '_to_upper']" -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME="createStringModule"
\n\n

كود JavaScript للعمل مع الذاكرة:

\n
const createStringModule = require('./string_ops.js');\n\ncreateStringModule().then(module => {\n    const { _string_length, _to_upper, heap } = module;\n    \n    // تخصيص ذاكرة للسلسلة\n    const input = "hello world";\n    const ptr = module._malloc(input.length + 1);\n    \n    // نسخ السلسلة إلى ذاكرة WASM\n    for (let i = 0; i < input.length; i++) {\n        heap[i + ptr] = input.charCodeAt(i);\n    }\n    heap[ptr + input.len                

المدونات

توصيات الكتب