Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: C-tyyliset callbackit ja C++

vidar [14.07.2008 20:19:01]

#

Onko mitään tapaa tai edes rumaa kikkaa saada C-tyylinen callback kutsumaan luokan jäsenfunktiota? Ideana olisi wrapata GLFW:n käyttö kätevään pikkuluokkaan. Kuitenkin ainoaksi tavaksi esimerkiksi unicode-inputin lukemiseen näppäimistöltä GLFW tarjoilee callbackkejä. Mokomat ovat tyyppiä void (*)(int, int), joten this-pointterin lähettäminen userdatanakaan ei pelitä, niinkuin joissain threadikirjastoissa. Tarkoitus olisi saada callbackit kutsumaan virtuaalisia key_down()/up()/etc -metodeita, jotta periytetyt luokat sitten saisivat hoitaa itse näppäin-häslinkinsä. Koitin alustavasti singletonin tekemistä, mutta periyttäminen kusee, kun täytyisi kutsua staattista metodia instanssin hakemiseen. Boostin/std:n bindit ja mem_fun:t etc eivät myöskään taida oikein sopia tähän. Eli, suunnitteluratkaisuja. Yksi vaihtoehto olisi tietty käyttää SDL:ää, joka hoitaa näppäimistön lukemisen eri tavalla, mutta kovasti kerkesin jo tykästyä tuohon GLFW:hen.

Metabolix [14.07.2008 21:09:44]

#

Mistäs ajattelit sitten sen this-osoittimen saada mukaan? Jos se olisi joka tapauksessa "funktio-osoittimessa" mukana, eikö ole sama tehdä funktio suoraan näin:

Luokka *luokka;

void funktio(int a, int b) {
  luokka->funktio(a, b);
}

Konekielen tiiviin funktiokutsumenettelyn takia omien ylimääräisten parametrien välittäminen on mahdotonta. Ainoa keino on yllä kuvaamani kaltainen apufunktio, joka täytyy tietenkin kirjoittaa jo ohjelmakoodiin, jos ratkaisusta haluaa saada arkkitehtuuri- ja käyttöjärjestelmäriippumattoman. Jos annettu osoitin (Luokka*) on osoitin kullakin hetkellä aktiiviseen käsittelijäluokkaan, homman pitäisi toimia aivan yhtä lailla kuin virtuaalisen funktion kutsumisen suoraankin. Joutuisit joka tapauksessa ilmeisesti muuttamaan jotakin aina käsittelijän vaihtuessa, niin mikset sitten tuota osoitinta? Voit tietenkin tehdä oman funktion set_callback_object.

Aiheesta lisää tällä sivulla, erityisesti toisessa osiossa: http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.2

(Toki on mahdollista kirjoittaa muistiin ohjelmakoodia myös ohjelman aikana, mutta koodi toimii vain yhdellä prosessoriarkkitehtuurilla, ja jotkin käyttöjärjestelmät estävät tällaisen itse luodun koodin ajamisen.)

Jos systeemisi on joka tapauksessa ohjelmassa ainoa laatuaan, kannattaa ehkä harkita, olisiko olion sijaan hyvä käyttää vain omaa nimiavaruutta.

vidar [14.07.2008 23:02:03]

#

Muistui vaan mieleen hiukka vastaava ongelma joskus SDL:n threadien kanssa, joissa callbackeille pystyi passaamaan voidipointterin threadin luontivaiheessa.

luokka::luokka() {
    saie = SDL_CreateThread(luokka::aja, this);
}

int luokka::aja(void* p) {
   luokka* self = static_cast<luokka*>(p);
   ...
}

Mutta joo, eihän tuo samanlainen systeemi ole.

No, sain kursittua kokoon jotain staattisen luokka* -pointterin kanssa, johon sijoitetaan this muodostimessa. Tuskimpa kuitenkaan tuosta tulee montaa instanssia luotua, ja pitäisi toimia periytettyjenkin luokkien kanssa. Kiitoksia.

Metabolix [15.07.2008 08:20:43]

#

Eihän tällä asialla varsinaisesti ole merkitystä niiden useamman instanssin kannalta, kun GLFW on kuitenkin rajoittava tekijä: sille voi rekisteröidä vain yhden callback-funktion kerrallaan, joten joka tapauksessa vain viimeinen instanssi saisi viestit.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta