0Pricing
Lua Academy · บทเรียน

ฟังก์ชันเรียกกลับ: การส่งฟังก์ชัน Lua ให้ C

ใช้ ffi.cast เพื่อสร้างฟังก์ชันเรียกกลับของ C ที่เรียกโค้ด Lua กลับได้

ฟังก์ชันเรียกกลับ: การส่งฟังก์ชัน Lua ให้ C เป็นบทเรียน Lua Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Lua Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน

การเรียกกลับของ C คืออะไร

API ของ C บางรายการกำหนดให้คุณส่งพอยน์เตอร์ฟังก์ชันที่โค้ด C จะเรียกกลับ FFI มี ffi.cast ซึ่งช่วยสร้างพอยน์เตอร์ฟังก์ชันที่เข้ากันได้กับ 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

การเรียกกลับและโครูทีน

การเรียกกลับของ Lua ที่ถูกเรียกจาก C ไม่สามารถ yield หรือเรียก coroutine.yield ได้ ฝั่ง C ไม่รองรับการสลับโครูทีนของ 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 ทำให้ควบคุมโครูทีนและการจัดการข้อผิดพลาดได้อย่างเต็มที่

ประสิทธิภาพ

การเรียกกลับของ FFI ทำงานได้รวดเร็ว แต่ไม่เร็วเท่าการเรียก FFI โดยตรง เนื่องจากสะพานเชื่อมจาก C ไป Lua มีค่าใช้จ่ายในการเตรียมการ สำหรับการเรียกกลับที่ถี่มาก เช่น เสียง ให้พิจารณาการนำไปใช้งานด้วย C ล้วน

คำถามเรื่องฟังก์ชันเรียกกลับ

เหตุใดจึงต้องเก็บการอ้างอิง Lua ไปยังออบเจ็กต์ฟังก์ชันเรียกกลับของ FFI ไว้

ทบทวน: ฟังก์ชันเรียกกลับของ FFI

ใช้ ffi.cast("fn_ptr_type", luaFunc) เพื่อสร้างฟังก์ชันเรียกกลับที่เข้ากันได้กับ C โปรดเก็บการอ้างอิงไว้เสมอเพื่อป้องกันตัวเก็บขยะ ฟังก์ชันเรียกกลับไม่สามารถ yield ได้ ใช้ค่าจากขอบเขตภายนอกเพื่อส่งบริบทเข้าสู่ฟังก์ชันเรียกกลับ

คำถามที่พบบ่อย

บทเรียน “ฟังก์ชันเรียกกลับ: การส่งฟังก์ชัน Lua ให้ C” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ฟังก์ชันเรียกกลับ: การส่งฟังก์ชัน Lua ให้ C” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Lua Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ฟังก์ชันเรียกกลับ: การส่งฟังก์ชัน Lua ให้ C”

ใช้ ffi.cast เพื่อสร้างฟังก์ชันเรียกกลับของ C ที่เรียกโค้ด Lua กลับได้ คุณปฏิบัติ Lua Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Lua Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Lua Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ฟังก์ชันเรียกกลับ: การส่งฟังก์ชัน Lua ให้ C” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Lua Academy นี้ได้ไหม

ได้ บทเรียน Lua Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐาน FFI: ffi.cdef และ ffi.load
  2. การเรียกฟังก์ชัน C ผ่าน FFI
  3. พอยน์เตอร์ โครงสร้าง และอาร์เรย์ใน FFI
  4. ฟังก์ชันเรียกกลับ: การส่งฟังก์ชัน Lua ให้ C
← กลับไปที่ Lua Academy