Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Vláďa J 08. 10. 2013, 12:16:38

Název: Použití knihovny (C++)
Přispěvatel: Vláďa J 08. 10. 2013, 12:16:38
Ahoj,

před časem jsem si pro svoje potřeby napsal hudební přehrávač v PySide (Python + Qt), který používám v autě na tabletu s Windows 7. Problém je v tom, že použitý backend Phonon je ve spojení s DirectShow extrémně nespolehlivý a jsem stále zaseknutý na starých Qt 4 knihovnách. Nezdá se, že by projekt PySide někdy v dohledné době podporu Qt 5 přidal. Kromě toho bych rád můj púřehrávač portoval i na Android a Ubuntu Touch.

Zkrátka situace dospěla do bodu, kdy je nutné přejít z Pythonu na C++. A to je problém, protože C++ skoro vůbec neznám. Není problém implementovat valnou část funkcí v JavaScriptu přímo v QML. Moje původní idea byla, že celý přehrávač bude jenom QML a jediné, na co použiju C++ bude načtení souborů na disku (to přímo z QML nelze). Celé by klaplo nebý toho, že QML objek pro přehrávání MediaPlayer a jeho metaData nefunguje ve Windows a na Androidu jenom omezeně. Načíst vešekrý možný tagy a podle nich vyhledávat v kolekci je přitom základní věc, kterou od přehrávače chci a proč si programuju svůj vlastní.

V Pythonu jsem používal knihovnu MediaInfo, která toho umí načíst opravdu hodně. Bohužel neumí zapisovat dp tagů. Bez toho bych se lehce obešel, ale nenašel jsem nikde verzi pro Android. Takže bych si jí musel nejspíš sám zkompilovat. A když už kompilovat nějakou céčkovou knihovnu, tak proč ne třeba TagLib, která umí všechno. Prostě váhám a nemám dost informací k tomu, abych se mohl rozhodnout. :-)

Za prvé mi není úplně jasný, jaký je z mého pohledu rozdíle mezi dynamickou a statiskou knihovnou. Předpokládám, že pokud používám dynamickou, stačí mi už předem zkompilovaná .dll knihovna (jako jsem jí používal v Pythonu). TagLib je distribuovaná jenom ve formě zdrojáku, takže si jí musím sám zkompilovat, ale to by asi neměl být výrazný problém. Kdybych chtěl použít knihovnu staticky, je to dobrý nápad? Má to pro mě nějaké výhody nebo naopak nevýhody?

Co všechno potřebuju k tomu, abych knihovnu mohl používat? Stačí .dll nebo k tomu potřebuju i hlavičkový soubor? Co je zač soubor s příponou .a? Jak se liší v .cpp souboru použití dynamický a statický knihovny?

Budu rád za odkaz na nějaký text, kde to je vysvětlené. Bohužel skoro všechno, co je na internetu, se týká obyčejného C. Jako IDE používám QtCreator, ale to by asi nemělo hrát zásadní vliv.

Omlouvám se za tolik omáčky okolo. Ale chtěl jsem vysvětlit, že programovat umím a nepředstavuju si to jako Hurvínek válku. Akorát neznám C++ a nechci zabíhat víc do hloubky než je nutný. Většinu věcí chci dělat v JavaScriptu a v C++ pouze načíst adresářový strom (to už mám implementované) a potom soubor po souboru načtat tagy a ukládat je do databáze (to už bude zase v QML přes QSql).
Název: Re:Použití knihovny (C++)
Přispěvatel: Sten 08. 10. 2013, 13:48:55
Za prvé mi není úplně jasný, jaký je z mého pohledu rozdíle mezi dynamickou a statiskou knihovnou. Předpokládám, že pokud používám dynamickou, stačí mi už předem zkompilovaná .dll knihovna (jako jsem jí používal v Pythonu). TagLib je distribuovaná jenom ve formě zdrojáku, takže si jí musím sám zkompilovat, ale to by asi neměl být výrazný problém. Kdybych chtěl použít knihovnu staticky, je to dobrý nápad? Má to pro mě nějaké výhody nebo naopak nevýhody?

Dynamické knihovny jsou výhodné prakticky jen pokud jsou distribuovány v balíčcích nebo pokud jsou LGPL a vy nechcete váš program vydat pod GPL. Na Androidu je navíc celkem složité linkování a je lepší se tam vlastním dynamickým knihovnám vyhnout.

Co všechno potřebuju k tomu, abych knihovnu mohl používat? Stačí .dll nebo k tomu potřebuju i hlavičkový soubor?

Je potřeba i hlavičkový soubor. U windowsího .dll je potřeba ještě soubor .lib.

Co je zač soubor s příponou .a?

.a je zkompilovaná statická knihovna, je to vlastně archiv mnoha .o souborů.

Jak se liší v .cpp souboru použití dynamický a statický knihovny?

V normálních systémech (Linux, Android, MacOS X, iOS, …) nijak. Ve Windows musí být všechny funkce, které chcete používat, exportované v dynamické knihovně a importované v hlavičkovém souboru.

Budu rád za odkaz na nějaký text, kde to je vysvětlené. Bohužel skoro všechno, co je na internetu, se týká obyčejného C.

Knihovny pro C a pro C++ fungují totožně.
Název: Re:Použití knihovny (C++)
Přispěvatel: Vláďa J 08. 10. 2013, 15:13:31
Díky moc za rady. Takže to zkusím přilinkovat staticky a uvidím, jestli se mi to nějak podaří rozběhat...

Název: Re:Použití knihovny (C++)
Přispěvatel: Ivan 08. 10. 2013, 16:26:18
Taky pisu multiplatformni aplikaci v QT.
A tohle jsou moje poznatky:
- moznosti knihoven na Woknach jsou mnohem omezenejsi nez na Linuxu. (nejedna se jen o exportovani symbolu)
- build system CMAKE (usetri ti spoustu problemu)
- Visual Studio Express (je zadarmo a MSVC je velice dobry kompilator + ma perfekni debuger)
- MSVC a MingW maji jine ABI pro C++. Kdyz zacnes michat knihovny s ruznym ABI zadelas si spoustu hnusnych problemu
Název: Re:Použití knihovny (C++)
Přispěvatel: x14 08. 10. 2013, 22:52:12
Jen doplním, že ve Windows je možné použít DLL soubor pomocí GetProcAddress(LoadLibrary("knihovna.dll"),"JménoVyexporovanéFunkce"), není k tomu zapotřebí nic dalšího.
Název: Re:Použití knihovny (C++)
Přispěvatel: Sten 08. 10. 2013, 23:35:51
Jen doplním, že ve Windows je možné použít DLL soubor pomocí GetProcAddress(LoadLibrary("knihovna.dll"),"JménoVyexporovanéFunkce"), není k tomu zapotřebí nic dalšího.

To ale pro C++ nebude moc příjemné kvůli name manglingu
Název: Re:Použití knihovny (C++)
Přispěvatel: Ivan 09. 10. 2013, 09:51:47
Joo jeste neco:
- dumpbin - je jeco jako nm na Unixu
- depwalk - je neco jako ldd na Unixu
Název: Re:Použití knihovny (C++)
Přispěvatel: Vláďa J 09. 10. 2013, 10:35:23
Já používám MinGW verzi Qt. Chtěl bych to všechno kompilovat pomocí toho.

Pokud se tedy vrátím k té TagLib knihovně. Jak ji mám konkrétně použít?

Nakopíroval jsem celý adresář "taglib" s .h a .cpp soubory do adresáře s mým projektem. V potom uvedu v mém kódu #include "taglib/tag.h". Ale při kompilaci nastane problém, že soubory v adresáři taglib linkujou další soubory, které jsou ale v podadresářích a překladač je nevidí. Proč to tak TagLib má? Co s tím?
Název: Re:Použití knihovny (C++)
Přispěvatel: Vláďa J 25. 10. 2013, 10:31:13
Tak nakonec jsem si zkompiloval TagLib samostatně pomocí CMake a gcc z command lajny. Pak jí v mym projektu linkuju dynamicky a zdá se, že všechno funguje tak, jak má. Díky všem za rady!
Název: Re:Použití knihovny (C++)
Přispěvatel: jholas 25. 10. 2013, 13:17:10
Jen doplním, že ve Windows je možné použít DLL soubor pomocí GetProcAddress(LoadLibrary("knihovna.dll"),"JménoVyexporovanéFunkce"), není k tomu zapotřebí nic dalšího.

To ale pro C++ nebude moc příjemné kvůli name manglingu

a co takhle deklarovat interface té knihovny jako extern "C" ?
Problém by byl maximálně s třídama, ale to se dá řešit např "CreateInstance" factory metodou.
Název: Re:Použití knihovny (C++)
Přispěvatel: Sten 25. 10. 2013, 13:53:49
Jen doplním, že ve Windows je možné použít DLL soubor pomocí GetProcAddress(LoadLibrary("knihovna.dll"),"JménoVyexporovanéFunkce"), není k tomu zapotřebí nic dalšího.

To ale pro C++ nebude moc příjemné kvůli name manglingu

a co takhle deklarovat interface té knihovny jako extern "C" ?
Problém by byl maximálně s třídama, ale to se dá řešit např "CreateInstance" factory metodou.

extern "C" je dost omezující (nefungují prostory jmen, přetěžování, nefunguje pro třídy). CreateInstance problém se třídami neřeší, protože nebude fungovat RTTI ani výjimky.

Další problémy: statické proměnné budete mít víckrát, což hodně věcí rozbije (třeba I/O streamy nebudou fungovat správně). Šablony budete mít víckrát, takže aplikace nabobtná (a šablony v knihovně budou mít opět jiné RTTI než ty samé šablony v aplikaci).

Ale proč to řešit složitě, když to jde jednoduše pomocí linkeru? :-)
Název: Re:Použití knihovny (C++)
Přispěvatel: jholas 25. 10. 2013, 14:01:14
Sten: protože to "jakž-takž" jde a programátoři mají rádi výzvy :-) a hlavně to bylo zmíněný jako možnost. Ale souhlasím, že pokud to nevyžaduje konkrétní řešení, tak je lepší to spojit pomocí linkeru.