Pro C++ experty.

gamer

Re:Pro C++ experty.
« Odpověď #15 kdy: 03. 12. 2015, 15:54:08 »
Mimochodem když už jsme u těch špinavých hacků, tak to co chceš udělat (alokovat určitou oblast paměti a v ní vytvořit třídu), se dělá pomocí placement new (https://isocpp.org/wiki/faq/dtors#placement-new). Ale pro tvůj účel (zajištění binární kompatibility) to rozhodně nedoporučuju.


Ivan

Re:Pro C++ experty.
« Odpověď #16 kdy: 03. 12. 2015, 16:06:34 »
Pozrel by som sa ako na to ide Qt ktora ma velmi dobru ABI kompatibilitu. Tam ma kazda trieda len jednu privatnu member premennu a to je pointer na instanciu privatnej triedy ktora drzi vsetko potrebne member premenne. Tym padom je potom velkost public triedy velmi stabilna napriec verziami kniznice. A ziadnu factory metodu nepotrebujete.

Ono z toho vychazi i KDE. Tady to maji pekne popsay.https://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B

Java ma v tomhle obrovskou vyhodu, ze jeji executable format uklada hash signatury metod. Takze se vam nemuze stat, ze zavolate metodu tridy ktera zabira 60 bajtu na zasobniky, zatimco jeji knihovni metoda si mysli, ze ma 64 bajtu. Mel jsem kolegu, ktery byl schotny tyhle veci vycist z ELF formatu. My obycejni smrtelnici se musime smirit s tim, ze zmeny v ABI mohou vest k nahodnym, tezko resitelnym segfaltum.

Jedna z moznosti jak to obejit, je nedelat zadny knihovny a svechni mit v templatech. Pomoci CRTP se da dosahnout i toho, ze i virtualni fce jsou inline a nepotrabuji zadne RTTI. Vysledky kod, je ale tezko udrzovatelny.

bjarne

Re:Pro C++ experty.
« Odpověď #17 kdy: 03. 12. 2015, 16:07:50 »
Ten přetížený new operátor bude implementovat ta třída z té knihovny.

Takže globální operátor new aplikace se přetíží v nějaké dynamické knihovně? To opravdu není dobrý nápad. Ono to navíc ani pořádně nefunguje: http://stackoverflow.com/questions/1054697/why-isnt-my-new-operator-called

Bude takhle - přeložením hlavní aplikace vznikne mimojiné např. knihovna core.dll, se kterou se budou linkovat pluginy (třeba plugin1.dll). Ta core.dll knihovna by případně mohla přetížit i ten globální new operátor.
Požadavky: exportované třídy z core.dll by měly mít možnost měnit svoje datové členy a hierarchii dědění, instance exportovaných třídy budou vytvářeny jen na haldě, takže dynamickou alokací
Co není potřeba: není potřeba, aby exportovaní třídy z core.dll šly podědit v pluginech, veškerá manipulace s datovými členy tříd bude probíhat přes metody.

gamer

Re:Pro C++ experty.
« Odpověď #18 kdy: 03. 12. 2015, 16:15:45 »
Bude takhle - přeložením hlavní aplikace vznikne mimojiné např. knihovna core.dll, se kterou se budou linkovat pluginy (třeba plugin1.dll). Ta core.dll knihovna by případně mohla přetížit i ten globální new operátor.

Proč to chceš hackovat přetěžováním operátoru new a nepoužiješ standardní řešení s čistě abstraktní bázovou třidou sloužící jako interface?

Tomas__

Re:Pro C++ experty.
« Odpověď #19 kdy: 03. 12. 2015, 16:18:04 »
nam se osvedcilo toto:

class A {
public:
A();
virtual ~A();

void neco();
virtual void necoJineho();

private:
class AImpl *impl;
};

Trik je v tom impl. Struktura je vzdy stejna i kdyz pridavas fieldy, metody apod, protoze je vse ulozene v impl, ktery je neznamej (neni v public headeru). virtualni destruktor mimo jine zajisti virtualni tabulku (nezmeni velikost ani pridanim dalsich metod). Jinak pracujes normalne s "new".

Na projektu jsme meli asi 60 DLL knihoven a patche fungovali velmi dobre i kdyz menili velmi podstatne funkcionalitu.





bjarne

Re:Pro C++ experty.
« Odpověď #20 kdy: 03. 12. 2015, 16:18:39 »
Mimochodem když už jsme u těch špinavých hacků, tak to co chceš udělat (alokovat určitou oblast paměti a v ní vytvořit třídu), se dělá pomocí placement new (https://isocpp.org/wiki/faq/dtors#placement-new). Ale pro tvůj účel (zajištění binární kompatibility) to rozhodně nedoporučuju.

Jo ten placement new by teoreticky mohl pomoct. Ono vlastně to i zřejmě odpovídá na tu moji otázku, to mě nenapadlo, díky :D

Protože to moje

Kód: [Vybrat]
class TridaZKnihovny {
}
void* opeator new(size_t size) { return std::malloc(sizeof(TridaZKnihovny);}

}
a pak v kodu

Kód: [Vybrat]
TridaZKnihovny* instance = new TridaZKnihovny();
muzu nahradit taky jako

Kód: [Vybrat]
class TridaZKnihovny {

static size_t getSize() { return sizeof(TridaZKnihovny); }

}

a v kodu

Kód: [Vybrat]
TridaZKnihovny* instance = new (std::malloc(TridaZKnihovny::getSize()) TridaZKnihovny();
A protoze vysledek by mel byt stejny, tak je defakto zajistene, ze ten parametr
Kód: [Vybrat]
size u opeatoru
Kód: [Vybrat]
new skutecne odpovida ciste jen velikosti te tridy a neni tam zahrnuto nic dalsiho.

bjarne

Re:Pro C++ experty.
« Odpověď #21 kdy: 03. 12. 2015, 16:27:54 »
nam se osvedcilo toto:

class A {
public:
A();
virtual ~A();

void neco();
virtual void necoJineho();

private:
class AImpl *impl;
};

Trik je v tom impl. Struktura je vzdy stejna i kdyz pridavas fieldy, metody apod, protoze je vse ulozene v impl, ktery je neznamej (neni v public headeru). virtualni destruktor mimo jine zajisti virtualni tabulku (nezmeni velikost ani pridanim dalsich metod). Jinak pracujes normalne s "new".

Na projektu jsme meli asi 60 DLL knihoven a patche fungovali velmi dobre i kdyz menili velmi podstatne funkcionalitu.

Jenze prave me vadi to, ze kdyz bych chtel pridat dalsi interface (dalsi bazovou tridu), tak to musim udelat v AImpl a pak vsechny metody toho interfacu navic jeste pridat do te public tridy.

Kód: [Vybrat]
class AImpl {

void udelejNeco();
}

Kód: [Vybrat]
class A {

void udelejNeco() { m_impl->udelejNeco(); }
private:
AImpl* m_impl;
}


a ted si vymyslim dalsi interface,

Kód: [Vybrat]
class IContext {

void neco();
}

tak musim to prechozi zmenit na:

Kód: [Vybrat]
class AImpl : public IContext {
void udelejNeco();
}

Kód: [Vybrat]
class A {

void udelejNeco() { m_impl->udelejNeco(); }
void neco( m_impl->neco();)
private:
AImpl* m_impl;
}

To se mi vubec nelibi tohle, protoze pak budu chtit pridat dalsich 5 interface a budu porad neco takhle kopirovat, no co to je?

Franta.

Re:Pro C++ experty.
« Odpověď #22 kdy: 03. 12. 2015, 16:51:17 »

kozzi11

Re:Pro C++ experty.
« Odpověď #23 kdy: 03. 12. 2015, 17:20:47 »
no co to je?

C++ ...

JJ presne, skoda ze C++ nema alias this tak jako jazyk D, to se pak toto implmentuje nadherne
Citace
class AImpl {
    void udelejNeco();
}

class A {
    private AImpl m_impl;
    alias m_impl this;
}

bjarne

Re:Pro C++ experty.
« Odpověď #24 kdy: 03. 12. 2015, 17:28:45 »
no co to je?

C++ ...

JJ presne, skoda ze C++ nema alias this tak jako jazyk D, to se pak toto implmentuje nadherne
Citace
class AImpl {
    void udelejNeco();
}

class A {
    private AImpl m_impl;
    alias m_impl this;
}

Bohuzel musim pouzivat taky Qt, jinak bych hned skocil po nejakem lepsim jazyce, ktery se podobne jako C++ kompiluje primo do nativniho kodu.

kozzi11

Re:Pro C++ experty.
« Odpověď #25 kdy: 03. 12. 2015, 17:39:07 »
no co to je?

C++ ...

JJ presne, skoda ze C++ nema alias this tak jako jazyk D, to se pak toto implmentuje nadherne
Citace
class AImpl {
    void udelejNeco();
}

class A {
    private AImpl m_impl;
    alias m_impl this;
}

Bohuzel musim pouzivat taky Qt, jinak bych hned skocil po nejakem lepsim jazyce, ktery se podobne jako C++ kompiluje primo do nativniho kodu.

Jedna z veci co mi obcas na D chybi je binding pro Qt.

bjarne

Re:Pro C++ experty.
« Odpověď #26 kdy: 03. 12. 2015, 18:22:58 »
hehe, kouknu na forum D a vidim, ze zrovna dneska byl jako open-source uvolněn Swift od Applu

Re:Pro C++ experty.
« Odpověď #27 kdy: 03. 12. 2015, 23:16:33 »
Tedy tady je odborníků na C++ až se mi chce brečet.

Původně jsem chtěl tazateli poradit, ale neudělám to, nemyslím si, že by mou odpověď našel mezi tou hromadou nesmyslných blábolů

Jinak přetěžování new v C++ běžně používám. Zpravidla ale jako nějakou base třídu, z níchž pak dědím, abych ten způsob alokace dostal všude tam, kde ho potřebuju. Třeba tady

https://github.com/ondra-novak/lightspeed/blob/master/src/lightspeed/base/memory/dynobject.h#L67

gamer

Re:Pro C++ experty.
« Odpověď #28 kdy: 04. 12. 2015, 07:20:19 »
Jinak přetěžování new v C++ běžně používám. Zpravidla ale jako nějakou base třídu, z níchž pak dědím, abych ten způsob alokace dostal všude tam, kde ho potřebuju. Třeba tady

Tohle je úplně uhozený způsob udržení binární kompatibility, nebude to fungovat. Všichni se to snaží tazateli říct, ale on to nechce pochopit. Pak přijde "odborník" a doporučí podobnou blbost.

Nebude to fungovat třeba z toho důvodu, že default constructor je inline, takže se nevykoná v dynamické libce, ale u klienta. Správná velikost na správnou inicializaci objektu nestačí, musí být splněna celá řada další podmínek.

Re:Pro C++ experty.
« Odpověď #29 kdy: 04. 12. 2015, 08:27:53 »
Nebude to fungovat třeba z toho důvodu, že default constructor je inline, takže se nevykoná v dynamické libce, ale u klienta. Správná velikost na správnou inicializaci objektu nestačí, musí být splněna celá řada další podmínek.

Hlavně i kdyby nějak vyřešil ten problém s new, tak pořád tu bude možnost, že uživatel knihovny bude chtít vytvořit instanci té třídy na zásobníku.