abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
dnes 00:33 | Zajímavý projekt

Společnost MNT Research má v plánu na Crowd Supply spustit kampaň na podporu open source notebooku MNT Reform. Vývoj notebooku lze sledovat na Mastodonu.

Ladislav Hagara | Komentářů: 3
dnes 00:11 | Zajímavý software

Chcete si zahrát víceuživatelský tetris v terminálu? Stačí spustit ssh netris.rocketnine.space. Na straně serveru běží netris. Zdrojové kódy v programovacím jazyce Go jsou k dispozici pod licencí GPLv3.

Ladislav Hagara | Komentářů: 0
včera 19:44 | Nová verze

Po čtyřech měsících vývoje od vydání verze 4.10 byla vydána nová verze 4.11 svobodné náhrady proprietárních BIOSů a UEFI coreboot (Wikipedie). Na vývoji se podílelo 130 vývojářů. Provedli 1630 změn. Přidána byla podpora pro 25 mainboardů.

Ladislav Hagara | Komentářů: 0
včera 16:22 | Nová verze

Byla vydána verze 1.6.0 emulátoru terminálu Terminology (GitHub) postaveného nad EFL (Enlightenment Foundation Libraries). Přehled novinek v poznámkách k vydání.

Ladislav Hagara | Komentářů: 0
včera 14:22 | Komunita

Vydání verze 1.0 svobodného multiplatformního vektorového grafického editoru Inkscape se blíží. Registrovaní uživatelé mají možnost hlasovat o obrázku, který bude zobrazován v okně O Inkscapu. Vybírá se ze 124 návrhů.

Ladislav Hagara | Komentářů: 7
včera 10:55 | Nová verze

Byl aktualizován seznam 500 nejvýkonnějších superpočítačů na světě TOP500. V první desítce se nic nezměnilo. Nejvýkonnějším superpočítačem zůstává superpočítač Summit. Nejvíce superpočítačů v TOP500 má Čína (228). Český superpočítač Salomon klesl na 375. místo. Další přehledy a statistiky na stránkách projektu. V aktuálním žebříčku GREEN500 (GFlops/watts) superpočítač Summit klesl na 5. místo.

Ladislav Hagara | Komentářů: 3
včera 02:00 | Zajímavý článek

V novém příspěvku na blogu Purismu se můžete dočíst, jak pokračoval vývoj softwaru Librem 5 v říjnu. Vývojáři optimalizovali linuxové jádro a ovladače pro snížení spotřeby telefonu. Mezi další změny patří lepší integrace mezi aplikacemi pomocí knihovny libfolks, byly přidány nové funkce klávesnice, nastavení, shellu, kompozitoru a opraveno plno chyb.

okias | Komentářů: 3
včera 01:55 | Nová verze

Na Humble Bundle byla spuštěna akce Humble Book Bundle: Cybersecurity 2019 by Packt. Všech 22 videokurzů a elektronických knih věnovaných kybernetické bezpečnosti od nakladatelství Packt lze koupit za 15 dolarů. Peníze lze libovolně rozdělit mezi nakladatelství Packt, neziskovou organizaci Arthritis Foundation a Humble Bundle.

Ladislav Hagara | Komentářů: 0
18.11. 23:22 | Zajímavý článek

Ben Cox v článku Jak psát ovladače nepodporovaných USB zařízení pro uživatelský prostor ukazuje, jak reverzním inženýrstvím dospěl k vlastnímu ovladači userspace-vga2usb pro převodník a frame grabber Epiphan VGA2USB LR s již nepodporovaným linuxovým ovladačem od výrobce.

Fluttershy, yay! | Komentářů: 0
18.11. 22:44 | Zajímavý software

Multiplatformní nástroj Sourcetrail pro analýzu zdrojových kódů a jejich vizualizaci byl uvolněn jako open source. Představení nástroje na YouTube. Zdrojové kódy jsou k dispozici na GitHubu pod licencí GNU GPL 3.0. Další vývoj lze podpořit na Patreonu.

Ladislav Hagara | Komentářů: 0
Jaké hodinky nosíte (nejčastěji)?
 (24%)
 (6%)
 (15%)
 (55%)
Celkem 266 hlasů
 Komentářů: 25, poslední dnes 13:06
Rozcestník

www.AutoDoc.Cz

Dotaz: C++ callback

8.11. 17:14 __blr__
C++ callback
Přečteno: 489×
Zdravím,

potřeboval bych implementovat jednoduchou epoll smyčku, kdy ke každému deskriptoru potřebuju uložit callback. Jak známo, pokud nebudu používat statické metody, není možné použít &trida::metoda.

Dohledal jsem mnoho implementací "delegation/c++ method callback" z různých dob na různých verzích C++.

Rád bych se zeptat, jak dnes, tady a teď řešit tuto problematiku.

Díky

Odpovědi

8.11. 20:38 .
Rozbalit Rozbalit vše Re: C++ callback
A to "potřebuju" znamená co?
8.11. 22:28 rastos | skóre: 61 | blog: rastos
Rozbalit Rozbalit vše Re: C++ callback
Metóda nejakej triedy v C++ je vlastne obyčajná C funkcia, ktorá okrem obyčajných parametrov dostane jeden parameter navyše: this. Ja som stará škola, ale urobil by som jednoducho mapu, kde kľúčom je deskriptor a hodnotou je pointer na funkciu.

A pokiaľ treba funkcii "odovzdať this", tak by hodnotou v tej mape nebol pointer na funkciu, ale štruktúra, v ktorej je jeden pointer na objekt (,ktorého metódu treba zavolať) a jeden pointer na funkciu.
11.11. 12:44 luky
Rozbalit Rozbalit vše Re: C++ callback
https://en.cppreference.com/w/cpp/utility/functional/invoke
11.11. 14:16 Andrej | skóre: 47 | blog: Republic of Mordor | Zürich
Rozbalit Rozbalit vše Re: C++ callback
Jak známo, pokud nebudu používat statické metody, není možné použít &trida::metoda.

Huh? A tohle je "známo" odkdy? Že jsem to nějak nepostřehnul… Tady jsou "nestatické" metody a &třída::metoda:

#include <iostream>
#include <memory>
#include <string>
#include <tuple>

class BunchOfCallbacks {
 public:
  BunchOfCallbacks(std::string state) : state_(std::move(state)) {}

  void Callback1(const std::string& message) const {
    std::cout << "Callback1 (" << state_ << "): " << message << std::endl;
  }
  void Callback2(const std::string& message) const {
    std::cout << "Callback2 (" << state_ << "): " << message << std::endl;
  }

 private:
  const std::string state_;
};

int main() {
  const std::tuple<BunchOfCallbacks,
                   void (BunchOfCallbacks::*)(const std::string&) const>
      callbacks[]{
          {BunchOfCallbacks{"first state"}, &BunchOfCallbacks::Callback1},
          {BunchOfCallbacks{"second state"}, &BunchOfCallbacks::Callback2},
      };

  for (const auto& bunch_callback : callbacks) {
    const auto& bunch{std::get<0>(bunch_callback)};
    const auto callback{std::get<1>(bunch_callback)};

    (bunch.*callback)("Yay! I can select a callback!");
  }
}
ǑǦŹǓǕǙǞǺǨȞȬḔḦḰḾṊṎṸẄẌỖ
xkucf03 avatar 11.11. 14:28 xkucf03 | skóre: 48 | blog: xkucf03
Rozbalit Rozbalit vše Re: C++ callback

Bývá problém to předat do API nějaké céčkovské knihovny, ne?

Tam to často řeší tak, že kromě (statické) funkce lze předat i libovolný ukazatel, který se pak použije jako parametr při volání té funkce (tzn. tohle je způsob jak tam dostat to this nebo nějaký kontext)

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes
11.11. 16:43 Andrej | skóre: 47 | blog: Republic of Mordor | Zürich
Rozbalit Rozbalit vše Re: C++ callback

Máš pravdu, (implicitní) požadavek na interoperabilitu s C jsem tady úplně přehlédl. :-) Ano, tam by se to muselo řešit jinak.

Problém totiž je, že member pointer je dost podivná věc. Například sizeof(void (BunchOfCallbacks::*)(const std::string&)) je asi tak 16, což zjevně neodpovídá pointeru, se kterým by mohlo pracovat přímo C.

(Důvod pro velikost member pointeru nějak souvisí s tím, že skrz něj musí správně fungovat taky virtuální metody. Což je u tříd bez virtuálních metod celkem jedno, ale ta implementace už je zkrátka taková.)

Když to má spolupracovat s C, asi bych ten callback napsal jako virtuální metodu, tj. každý typ callbacku by byl třída. Tam se pak dá předat tomu C nějaký void* a vhodný C++ wrapper (viditelný z C) ho může interpretovat jako ukazatel na toho abstraktního předka a zavolat jeho virtuální metodu.

ǑǦŹǓǕǙǞǺǨȞȬḔḦḰḾṊṎṸẄẌỖ
11.11. 16:56 Andrej | skóre: 47 | blog: Republic of Mordor | Zürich
Rozbalit Rozbalit vše Re: C++ callback

Inu, epoll() neznám, takže příklad s epoll() tady narychlo nesesmolím, ale takhle by mohla (obecně) vypadat ta spolupráce s C (tady konkrétně s pthread):

#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <iostream>

namespace {
struct Callback {
  virtual void* call() = 0;
};

class ThreadWrapper {
  pthread_t thread_;

 public:
  ThreadWrapper(void* (*start_routine)(void*), void* arg) {
    if (-1 == pthread_create(&thread_, nullptr, start_routine, arg)) {
      throw errno;
    }
  }
  ~ThreadWrapper() {
    if (-1 == pthread_join(thread_, nullptr)) {
      std::cerr << "Join failed!\n";
    }
  }
};

void* ThreadBody(void* arg) { return static_cast<Callback*>(arg)->call(); }
}  // namespace

int main() {
  struct Callback1 : public Callback {
    void* call() override {
      std::cout << "I'm Callback 1!\n";
      return nullptr;
    }
  } callback1;
  struct Callback2 : public Callback {
    void* call() override {
      std::cout << "I'm Callback 2!\n";
      return nullptr;
    }
  } callback2;

  try {
    ThreadWrapper t1(ThreadBody, &callback1);
    ThreadWrapper t2(ThreadBody, &callback2);
  } catch (int e) {
    std::cerr << strerror(e) << std::endl;
  }
}

To^^^ pochopitelně vyžaduje -lpthread.

(Jasně, používat takhle v C++ pthread je nesmysl, protože C++ má už dávno (od dob Rapperswilu) na vlákna vhodnější abstrakce, nicméně tohle je míněno jako příklad na "callback mezi C a C++".)

ǑǦŹǓǕǙǞǺǨȞȬḔḦḰḾṊṎṸẄẌỖ
14.11. 14:17 Kojot
Rozbalit Rozbalit vše Re: C++ callback
std::function
17.11. 16:52 Jardík
Rozbalit Rozbalit vše Re: C++ callback
V čem je vlastně problém? V epoll_data můžeš mít vlastní pointer, to ti stačí. Můžeš si dynamicky naalokovat klidně std::function, kde budeš mít cokoliv, pointer předáš při přidávání deskriptoru v epoll_event::data, po volání epoll_wait tento pointer dostaneš, přetypuješ na pointer na std::function, dereferencuješ a zavoláš. Nebo místo alokace std::function můžeš naalokovat strukturu, kde bude ukazatel na objekt a ukazatel na funkci a pak funkci zavoláš na ten objekt.

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267   www.czech-server.cz
© 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.