Qt Vlastní knihovny – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Qt Vlastní knihovny – C / C++ – Fórum – Programujte.comQt Vlastní knihovny – C / C++ – Fórum – Programujte.com

 

crow
~ Anonymní uživatel
14 příspěvků
22. 2. 2012   #1
-
0
-

Zdravim,

mám takový problém... chtěl jsem si vytvořit knihovnu (.dll), kde budu mít svoje nejpoužívanejší třídy/funkce, páč se mi to nechce stále kopírovat do projektů, ale nějak jsem narazil, že to asi nepůjde přesně tak, jak jsem si představoval :(

Pokud vytvořím projekt jako C++ knihovna, tak nechám vše default + přidám jen jednu fci (na test) do hlavičky a těla. V dalším projektu si ji načtu (pravý na projekt a vložit dynamickou knihovnu - tady nějak nechápu, proč to chce načítat .lib místo .dll).. a zde jsem už předpokládal, že budu moct bez problémů použít něco jako:

#include <MojeAPI> nebo něco v tom stylu, abych to mohl třídit jako <api/network> atd.

Můžete mi někdo poradit jak na to? Sice jsem něco už našel na netu, ale to je snad na 20 řádků, ale žádnej jednoduchej způsob jsem nenašel :( .. třeba jako v C# či VB.NET, kde stačilo přidat knihovnu do projektu a člověk mohl vesele usingovat, něco takovýho bych bral

Nahlásit jako SPAM
IP: 46.183.64.–
liborb
~ Redaktor
+18
Guru
23. 2. 2012   #2
-
0
-

Někde musí být řečeno, co je to za funkci, jaké má parametry (typy) a hlavně, kde v knihovně se nechází ... no a to je řečeno v .lib.

Pokud chceš princip ala C#, tak to míříš někam do COM, typových knihoven (typelib) a smart pointerů. Samozřejmě nevím, jak moc jsi zdatný, ale může se taky stát, že až do tohoto zabředneš, tak se ti bude zdát způsob přes .lib, tak jednoduchý a krásný, že na něj nedáš dopustit :).

Nahlásit jako SPAM
IP: 78.80.52.–
crow
~ Anonymní uživatel
14 příspěvků
23. 2. 2012   #3
-
0
-

Takže na každou fci, musí být typ? A nějaká možnost, jak zavolat z knihovny celou třídu, kde bych měl všechny fce neni? Na tohle jsem právě nenašel řešení na googlu

btw knihovna jako ".lib" je použitelná i na linuxu, nebo bych to musel skompilovat přes gcc nějak, aby z toho bylo ".so" ?

Nahlásit jako SPAM
IP: 46.183.64.–
liborb
~ Redaktor
+18
Guru
23. 2. 2012   #4
-
0
-

Stejně jako exportuješ funkci, tak budeš exportovat třídu, tj. ve VS nějak takto:

class __declspec(dllexport) CMojeTrida {

};

a pak je třída viditelná z dll v jiné dll nebo v exe (stačí inludovat hlavičku a přihodit libku). A ano, nějak tak by to mělo být i přes .so v linuxu, ale to není můj šálek kávy ;)

Nahlásit jako SPAM
IP: 78.80.52.–
ondra.holub+1
Stálý člen
23. 2. 2012   #5
-
+1
-
Zajímavé

#3 crow
Celou třídu nelze zavolat a je jedno, jestli ji máš v knihovně nebo třeba přímo v jediném zdrojáku. Můžeš volat jenom metody třídy, což jsou zase jenom funkce, které mají nějaké skryté parametry. Takže pokud chceš strčit do knihovny třídu, potřebuješ k jejímu použití deklaraci té třídy. A ta se obvykle dává do headeru. Takže pak budeš mít knihovnu a hlavičkový soubor (jeden nebo více).

.lib je formát statické knihovny, který používá např. ms visual c/c++. gcc produkuje .a Přípona .so je sdílená knihovna v některých unixech (např. v Linuxu), je to podobné jako .dll ve Windows.

Můžeš přeložit .dll třeba v gcc a použít ho v programu ve visual c (a naopak) pouze za předpokladu, že ta knihovna bude mít C API. C++ ti fungovat nebude, protože binární rozhraní (ABI) není kompatibilní. .lib lze v některých případech překonvertovat na .a nebo naopak, ale nemám s tím zkušenosti.

Žádná knihovna přeložená pro Windows ti nebude fungovat v Linuxu (a stejně tak naopak). Musíš si to přeložit buď v Linuxu znovu nebo si to můžeš přeložit i v jiném systému, ale potřebuješ k tomu cross-compiler, který sebou nese všechny knihovny z cílové platformy. Další možnost je mít celý program přeložený pro Windows (tedy hlavní binárku i knihovny) a pouštět ho v Linuxu přes Wine. Může to fungovat, ale nemusí a rozhodně to není triviální cesta (i když v některých případech to může být snazší, než přepsat program tak, aby byl multiplatformní).

Nahlásit jako SPAM
IP: 194.138.12.–
crow
~ Anonymní uživatel
14 příspěvků
23. 2. 2012   #6
-
0
-

Takže jestli dobře chápu, tak nemůžu použít nějakou třídu v knihovně, aniž bych v programu společně s přidáním LIBS +=  nepřidal i hlavičku té třídy? Tenhle způsob mi moc nevoní, co když budu chtít použít třeba od kamáráda .dll knihovnu co dělal pro Qt? Tak to mi musí poslat i hlavičku abych mohl použít celou třídu a hlavně nemusel volat jednotlivý fce samostatně?

Pokud ano, tak to mi přijde trochu zbytečný používat knihovnu, to rovnou můžu hodit do projektu :/

Nahlásit jako SPAM
IP: 46.183.64.–
KIIV
~ Moderátor
+43
God of flame
23. 2. 2012   #7
-
+1
-
Zajímavé

no k cemu ti je dll kdyz nevis co v ni je a jak to volat (pouzit?)

cely princip je v tom, ze kdyz ti kamarad posle  .h a .dll  tak to s tim zkompilujes (nicmene nemusis kompilovat celou jeho knihovnu!) a co je lepsi - pokud opravi knihovnu a posle ti novou verzi, melo by to fungovat (alespon dokud by nezmrsil rozhrani)

tj. princip je ze nemusis kompilovat jeho zdrojaky - staci ti jen predpis co to umi, a jak se to vola a ze se libka da vymenit aniz bys musel rekompilovat cely tvuj program

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
crow
~ Anonymní uživatel
14 příspěvků
23. 2. 2012   #8
-
0
-

Aha, takže neexistuje žádný jednoduchý řešení, že se do projektu přidá pouze .dll a ono si to samo už zjistí, co to všechno obsahuje, takže bych to mohl ihned používat? Mě stále trochu štve, že musim includovat i hlavičku, co když budu chtít použít knihovnu třetí strany, kde to bude dostupný pouze bez .h, takže to budu muset ručne typovat každou funkci?

Nahlásit jako SPAM
IP: 46.183.64.–
KIIV
~ Moderátor
+43
God of flame
23. 2. 2012   #9
-
0
-

tomu se rika pluginy a musis si tu aplikaci na to pekne pripravit, aby to vubec mohlo jit... a hlavne plugin pak bude mit velice jasnou strukturu a tak dale - nic lehkyho

Jinak nechapu co mas proti includum? (samozrejme pokud mas opravdu v hlavickovem souboru jen deklarace)

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
crow
~ Anonymní uživatel
14 příspěvků
23. 2. 2012   #10
-
0
-

Pouze deklarace tam mám, je to spíš zvyk z C#, kde stačilo přidat nějaký .dll a bez problémů šlo vše z .dll používat a bylo i vidět (pokud se nejednalo o C++ knihovnu, zde bylo nutný ruční include funkce (pokud byla statická))

Nahlásit jako SPAM
IP: 46.183.64.–
liborb
~ Redaktor
+18
Guru
23. 2. 2012   #11
-
0
-

To je jak jsem psal výše ... v C++ COM, typelib a smart pointer.

Na začátek kódu dáš: 

#import "jmeno_knihovny.dll" no_namespace

a instanci třídy (rozhraní) si vytvoříš přes smart pointer: 

INejakeJmenoPtr	pPointer(CLSID);

kde CLSID je GUID tvého COM objektu. No a pak už to jenom používáš :)

Nahlásit jako SPAM
IP: 78.80.52.–
Peppy0
Stálý člen
23. 2. 2012   #12
-
0
-

Takže, ako ja používam DLLky v C++ (aj s namespace):

namespace Projekt {
      class Trieda : public QObject {
          // ...
      };
}

Vlastný hlavičkový súbor a zdroják s exportami a typedef:

extern "C" 
{
   QDECL_EXPORT Projekt::Trieda* getTrieda(void);
}

typedef Projekt::Trieda* (*GetTriedaHandler) (void);

// .cpp:
Projekt::Trieda* getTrieda(void) 
{
    return new Projekt::Trieda(); 
}

v kóde treba už len správne zavolať pointer na funkciu.

Nahlásit jako SPAM
IP: 85.135.144.–
Qt, QML, C++
crow
~ Anonymní uživatel
14 příspěvků
23. 2. 2012   #13
-
0
-

#12 Peppy
Tohle celý máš v .dll jo? a jak to potom voláš v projektu? však to stejně nebude vidět ne?

Nahlásit jako SPAM
IP: 46.183.64.–
Peppy0
Stálý člen
23. 2. 2012   #14
-
0
-

1. bude vidieť.
2. A volám to pomocou QLibrary:

(void *) QLibrary::resolve(...);

Nahlásit jako SPAM
IP: 85.135.144.–
Qt, QML, C++
ondra.holub+1
Stálý člen
23. 2. 2012   #15
-
0
-

#14 Peppy
A v čem je to jednodušší proti běžnému #include neco a stejnému používání, jako když to není v extra knihovně? 

Předpokládám, že QLibrary::resolve je nějaký wrapper na dlopen a obdobnou funkci z Windows API.

Nahlásit jako SPAM
IP: 212.96.189.–
crow
~ Anonymní uživatel
14 příspěvků
23. 2. 2012   #16
-
0
-

#14 Peppy
No.. zkoušel jsem to co si psal a DLL mi skompilovat jde, ale nějak nechápu jak vyřešit to volání v projektu, to mi nějak nejde přes to QLibrary..
Mám "MyDLL.dll" jako:


Hlavička "mydll.h":



#include <QtCore>
#include <QObject>
#include <QDebug>

namespace MyDLL
{
    class Core : public QObject
    {
    public:
        void vypis(QString text);
    };
}

extern "C"
{
    Q_DECL_EXPORT MyDLL::Core *getMyDLL();
}

typedef MyDLL::Core *(*GetMyDLLHandler)();

Tělo "mydll.cpp":

#include "mydll.h"

MyDLL::Core *getMyDLL()
{
    return new MyDLL::Core();
}

void MyDLL::Core::vypis(QString text)
{
    qDebug() << text;
}

A teď nějak nechápu jak zavolat tu knihovnu .dll... mam prázdnej konzolovej projekt.. kde do "main.ccp" dám:

#include <QtCore/QCoreApplication>
#include <QLibrary>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    QLibrary ql;
    auto e = (void*) ql.resolve("MyDLL.dll");

    return a.exec();
}

QLibrary mi staticky zavolat nešla, takže jsem to udělal přes proměnnou, ale stále nějak nechápu, jak si zavolám a vytvořim instanci třídy z toho .dll (cesta k DLL je správná)

Nahlásit jako SPAM
IP: 46.183.64.–
crow
~ Anonymní uživatel
14 příspěvků
23. 2. 2012   #17
-
0
-

Jako pokud si v DLL udělám samotnou funkci, tak jí jde zavolat jako:

    typedef void (*Vypis)(QString);
    QLibrary *ql = new QLibrary("MyDLL.dll");
    Vypis vypis = (Vypis) QLibrary::resolve(file, "vypis");
    vypis("Ahoj svete");

Ale ten postup neni zrovna krátkej, krom toho se mi takto vůbec nedaří zavolat celou třídu - to právě řešim :(

Nahlásit jako SPAM
IP: 46.183.64.–
crow
~ Anonymní uživatel
14 příspěvků
23. 2. 2012   #18
-
0
-

pardon, špatný edit.. takto:

    typedef void (*Vypis)(QString);
    Vypis vypis = (Vypis) QLibrary::resolve("MyDLL.dll", "vypis");
    vypis("Ahoj svete");

kde, "vypis" je nazev funkce

Nahlásit jako SPAM
IP: 46.183.64.–
Peppy0
Stálý člen
24. 2. 2012   #19
-
0
-

Triedu sa ti nikdy nepodarí zavolať takto. Musíš si vytvoriť v DLL getter. O to tam ide.  Toto nie je C#. Áno, zdĺhavý to postup ale vedie to k tomu, čo chceš ty. Urobím ti example projekt a dakde ho dám.

Nahlásit jako SPAM
IP: 85.135.169.–
Qt, QML, C++
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 3 hosté

Podobná vlákna

Knihovny :P — založil Sony

Knihovny — založil Sony

Knihovny — založil yxcvb

Pridani knihovny — založil Mrkus

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý