Lua Academy · Oppitunti

Takaisinkutsut: Lua-funktioiden välittäminen C:lle

Luokaa ffi.cast-funktiolla C-takaisinkutsuja, jotka kutsuvat Lua-koodia.

Oppitunti 4/413 vaihetta

Takaisinkutsut: Lua-funktioiden välittäminen C:lle on ilmainen Lua Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Lua Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Lua Academy-kurssilla on yhteensä 4 oppituntia.

Mitä C-takaisinkutsut ovat?

Jotkin C-rajapinnat edellyttävät, että niille välitetään funktio-osoitin, jota C-koodi kutsuu myöhemmin. FFI:n ffi.cast-funktiolla Lua-funktioista voidaan luoda C-yhteensopivia funktio-osoittimia.

Takaisinkutsutyypin määrittely

Määritelkää ensin funktio-osoitintyyppi cdefissä.

local ffi = require("ffi")
ffi.cdef[[
  typedef void (*callback_t)(int event, void *data);
  void register_handler(callback_t cb);
]]

Takaisinkutsun luominen

Käärikää Lua-funktio C:n takaisinkutsuksi komennolla ffi.cast("callback_t", luaFunc). Tuloksena on C-funktio-osoitin, jonka voi välittää C-koodille.

local function myHandler(event, data)
  print("Event:", event)
end
local cb = ffi.cast("callback_t", myHandler)
lib.register_handler(cb)

Takaisinkutsun elinkaari

Säilyttäkää Lua-viite takaisinkutsuolioon (cb). Jos GC käsittelee sen, C-funktio-osoittimen kutsuminen kaataa ohjelman. Tallentakaa se pitkäikäiseen muuttujaan tai taulukkoon.

local callbacks = {}  -- prevent GC
callbacks[#callbacks+1] = ffi.cast("callback_t", myHandler)
lib.register_handler(callbacks[#callbacks])

Lajittelu C-vertailufunktiolla

Välittäkää Lua-vertailufunktio C:n qsort-funktiolle FFI-takaisinkutsun kautta.

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

Takaisinkutsut ja korutiinit

C:stä kutsutut Lua-takaisinkutsut eivät voi keskeyttää suoritusta (coroutine.yield). C-puoli ei tue Luan korutiinin vaihtamista. Suunnitelkaa takaisinkutsut niin, etteivät ne keskeytä suoritusta.

Upvalue-arvot takaisinkutsuissa

Lua-takaisinkutsut voivat sulkea upvalue-arvoja normaalisti. Näin takaisinkutsut voivat käyttää kontekstia (esimerkiksi oliota tai tilataulukkoa) ilman globaaleja muuttujia.

local function makeHandler(ctx)
  return ffi.cast("callback_t", function(event, _)
    ctx.lastEvent = event  -- upvalue access
  end)
end

Signaalinkäsittelijät

Rekisteröikää Lua-funktioita Unix-signaalinkäsittelijöiksi FFI:n kautta. Olkaa varovaisia: signaalinkäsittelijöillä on tiukat rajoitukset sille, mitä C-funktioita ne voivat kutsua.

Takaisinkutsujen muistinhallinta

Vapauttakaa takaisinkutsut komennolla cb:free(), kun olette poistaneet niiden rekisteröinnin C-puolelta. Takaisinkutsuolioiden vuotaminen tuhlaa muistia.

Vaihtoehto: C-wrapper-funktiot

Monimutkaisissa integraatioissa ohut C-sovitin voi olla FFI-takaisinkutsuja selkeämpi. Sovitin kutsuu Luaa C API:n kautta ja tarjoaa täyden hallinnan korutiineihin ja virheenkäsittelyyn.

Suorituskyky

FFI-takaisinkutsut ovat nopeita, mutta eivät yhtä nopeita kuin suorat FFI-kutsut, koska C:n ja Luan välinen silta aiheuttaa valmistelukustannuksia. Harkitkaa erittäin usein kutsuttavissa takaisinkutsuissa (esimerkiksi audiossa) puhtaasti C:llä toteutettuja ratkaisuja.

Callback-kysymys

Miksi FFI-takaisinkutsuobjektista on säilytettävä Lua-viite?

Kertaus: FFI-takaisinkutsut

Luokaa C-yhteensopivia takaisinkutsuja käyttämällä ffi.cast("fn_ptr_type", luaFunc)-kutsua. Säilyttäkää aina viite, jotta roskienkeruu ei poista objektia. Takaisinkutsut eivät voi yieldata. Välittäkää konteksti takaisinkutsuihin upvalue-arvojen avulla.

Aloita maksutta

Opi Lua tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
40
Oppitunnit
159

Usein kysytyt kysymykset

Onko oppitunti ”Takaisinkutsut: Lua-funktioiden välittäminen C:lle” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Lua Academy-oppimispolun 3 oppituntia, myös oppitunnin “Takaisinkutsut: Lua-funktioiden välittäminen C:lle”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Lua Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Takaisinkutsut: Lua-funktioiden välittäminen C:lle”?

Luokaa ffi.cast-funktiolla C-takaisinkutsuja, jotka kutsuvat Lua-koodia. Harjoittelet Lua Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Lua Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Lua Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Takaisinkutsut: Lua-funktioiden välittäminen C:lle”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Lua Academy-oppitunnilla?

Kyllä. Jokainen Lua Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. FFI:n perusteet: ffi.cdef ja ffi.load
  2. C-funktioiden kutsuminen FFI:n kautta
  3. Osoittimet, rakenteet ja taulukot FFI:ssä
  4. Takaisinkutsut: Lua-funktioiden välittäminen C:lle
← Takaisin: Lua Academy