دوال الاستدعاء العكسي: تمرير دوال Lua إلى C
استخدم ffi.cast لإنشاء دوال استدعاء عكسي في C تستدعي شيفرة Lua
دوال الاستدعاء العكسي: تمرير دوال Lua إلى C درس مجاني في Lua Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Lua Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Lua Academy 4 دروس في المجموع.
ما هي الاستدعاءات الراجعة في C؟
تتطلب بعض واجهات C تمرير مؤشر دالة تستدعيه شيفرة C لاحقًا. تتيح ffi.cast في FFI إنشاء مؤشرات دوال متوافقة مع C من دوال Lua.
تعريف نوع الاستدعاء الراجع
أعلنوا أولًا عن نوع مؤشر الدالة في cdef.
local ffi = require("ffi")
ffi.cdef[[
typedef void (*callback_t)(int event, void *data);
void register_handler(callback_t cb);
]]إنشاء استدعاء راجع
استخدموا ffi.cast("callback_t", luaFunc) لتغليف دالة Lua على شكل استدعاء راجع لـC. والنتيجة مؤشر دالة C يمكن تمريره إلى شيفرة C.
local function myHandler(event, data)
print("Event:", event)
end
local cb = ffi.cast("callback_t", myHandler)
lib.register_handler(cb)عمر الاستدعاء الراجع
احتفظوا بمرجع Lua إلى كائن الاستدعاء الراجع (cb). فإذا جمعه GC، فسيتسبب استدعاء مؤشر دالة C في انهيار البرنامج. خزّنوه في متغير أو جدول طويل العمر.
local callbacks = {} -- prevent GC
callbacks[#callbacks+1] = ffi.cast("callback_t", myHandler)
lib.register_handler(callbacks[#callbacks])الفرز باستخدام مقارن C
مرّروا دالة مقارنة من Lua إلى qsort في C عبر استدعاء راجع من FFI.
ffi.cdef[[
typedef int (*cmp_t)(const void *a, const void *b);
void qsort(void *base, size_t nmemb, size_t size, cmp_t cmp);
]]
local arr = ffi.new("int[5]", {3,1,4,1,5})
local cmp = ffi.cast("cmp_t", function(a, b)
return ffi.cast("int*", a)[0] - ffi.cast("int*", b)[0]
end)
ffi.C.qsort(arr, 5, ffi.sizeof("int"), cmp)
for i = 0, 4 do io.write(arr[i] .. " ") endالاستدعاءات الراجعة وCoroutines
لا يمكن للاستدعاءات الراجعة من Lua التي تستدعيها C أن تتوقف مؤقتًا باستخدام coroutine.yield. فالجانب C لا يدعم تبديل coroutine في Lua. صمّموا الاستدعاءات الراجعة بحيث لا تتوقف مؤقتًا.
القيم الصاعدة في الاستدعاءات الراجعة
يمكن للاستدعاءات الراجعة في Lua التقاط القيم الصاعدة كالمعتاد. ويتيح ذلك لها الوصول إلى السياق، مثل كائن أو جدول حالة، من دون استخدام متغيرات عامة.
local function makeHandler(ctx)
return ffi.cast("callback_t", function(event, _)
ctx.lastEvent = event -- upvalue access
end)
endمعالجات الإشارات
سجّلوا دوال Lua كمعالجات لإشارات Unix عبر FFI. توخّوا الحذر، إذ تفرض معالجات الإشارات قيودًا شديدة على دوال C التي يمكنها استدعاءها.
إدارة ذاكرة الاستدعاءات الراجعة
حرّروا الاستدعاءات الراجعة باستخدام cb:free() بعد إلغاء تسجيلها من جانب C. فتسرّب كائنات الاستدعاءات الراجعة يهدر الذاكرة.
بديل: دوال تغليف C
قد يكون غلاف C رقيق للتكاملات المعقدة أنظف من استدعاءات FFI الراجعة. إذ يستدعي الغلاف Lua عبر واجهة C API، مما يمنحكم تحكمًا كاملًا في coroutine ومعالجة الأخطاء.
الأداء
تتميز الاستدعاءات الراجعة عبر FFI بالسرعة، لكنها ليست بسرعة استدعاءات FFI المباشرة، لأن الجسر من C إلى Lua يتطلب وقتًا إضافيًا للإعداد. وبالنسبة إلى الاستدعاءات ذات التواتر العالي جدًا، مثل الصوت، فكّروا في تطبيقات C خالصة.
سؤال حول دوال الاستدعاء اللاحق
لماذا يجب الاحتفاظ بمرجع Lua إلى كائن دالة الاستدعاء اللاحق الخاصة بـ FFI؟
مراجعة: دوال الاستدعاء اللاحق في FFI
استخدم ffi.cast("fn_ptr_type", luaFunc) لإنشاء دوال استدعاء لاحق متوافقة مع C. احرص دائمًا على تخزين مرجع لمنع جامع القمامة من تحريرها. لا يمكن لدوال الاستدعاء اللاحق تنفيذ yield. استخدم upvalues لتمرير السياق إلى دوال الاستدعاء اللاحق.
الأسئلة الشائعة
هل درس «دوال الاستدعاء العكسي: تمرير دوال Lua إلى C» مجاني؟
نعم — نص درس «دوال الاستدعاء العكسي: تمرير دوال Lua إلى C» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Lua Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Lua Academy 4 دروس في المجموع.
ماذا ستتعلم في «دوال الاستدعاء العكسي: تمرير دوال Lua إلى C»؟
استخدم ffi.cast لإنشاء دوال استدعاء عكسي في C تستدعي شيفرة Lua تتمرن على Lua Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Lua Academy؟
لا تُشترط خبرة سابقة. Lua Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «دوال الاستدعاء العكسي: تمرير دوال Lua إلى C»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Lua Academy هذا؟
نعم. كل درس في Lua Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات FFI: ffi.cdef وffi.load
- استدعاء دوال C عبر FFI
- المؤشرات والبُنى والمصفوفات في FFI
- دوال الاستدعاء العكسي: تمرير دوال Lua إلى C