Použití dll v C – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

Použití dll v C – C / C++ – Fórum – Programujte.comPoužití dll v C – C / C++ – Fórum – Programujte.com

 

Hledá se programátor! Plat 1 800 € + bonusy (firma Boxmol.com)
etrix0
Newbie
12. 2. 2008   #1
-
0
-

Zdravím,

potřeboval bych napsat knihovnu v C a použít v programu který je napsán v C. Postupoval jsem podle http://www.zezula.net/cz/prog/vytvoreni_dll.html ale tam se jedná o Visual C++.

Neměl byste někdo nějaký příklad jak to jednoduše vytvořit a použít v C za pomocí gcc?

Nahlásit jako SPAM
IP: 90.176.59.–
Reklama
Reklama
Jura
~ Anonymní uživatel
634 příspěvků
12. 2. 2008   #2
-
0
-

Zdravím,

otázkou je, co myslíš tím jednoduše. Já bych třeba využil nějakého prostředí, nejspíše code::blocks a v něm si vytvořil projekt dll a o více se nestaral a pak bych už jen jednoduše udělal buil té knihovny. Jsem si jistý, že se teď ozvou zarytí zastánci gcc(v tomhle případě asi mingw), ale v tomhle případě to snad přehlídnou;)

Nahlásit jako SPAM
IP: 85.207.192.–
etrix0
Newbie
12. 2. 2008   #3
-
0
-

Jednoduše myslím prostě přehledné vytvoření a použití. Mám gcc (mingw) a pak bych nejradši chtěl jen jeden zdroják (dll) a druhej zdroják (program používající dll). Zkoušel jsem vytvořit dll v MSVC++Express, což se mi pravděpodobně povedlo (už je to asi rok), ale tomu neříkám přehlednost, jenom pro vytvoření dll to vyrobilo asi 11 různejch souborů pro MSVC. Nemluvě o tom šíleném použití dll v hlavním programu.

Jednoduchost bych potřeboval protože se to teprve učím. Nejlepší by bylo kdyby mi někdo poradil "Takhle napíšeš program -ukázková funkce-, skompiluješ do dll (gcc.exe dll.c -udelej_dll -o knihovna.dll) a načteš a použiješ dll takhle: ...".

Nahlásit jako SPAM
IP: 90.176.59.–
Jura
~ Anonymní uživatel
634 příspěvků
13. 2. 2008   #4
-
0
-

Pořád mi není jasné v čem je problém? Pokdu ti MSVC vygenerovalo několik souborů, tak pro tebe jsou důležité nejvýše 3, a to: samotná dll a pk volitelně *.lib(k tomu statickému přípojení, abys nemusel furt psát GetProcAddress) a *.h soubor. Pak už je použití naprosto triviální(*.lib knihovnu přídáš k cestám linkeru, *.h k projektu a *.dll k aplikaci).

Nahlásit jako SPAM
IP: 85.207.192.–
etrix0
Newbie
13. 2. 2008   #5
-
0
-

Problém je v tom, že bych chtěl vytvořit nezávislou externí dll v gcc. A použít ji v programu taky z gcc. MSVC ani teď nemám. Našel jsem tohle: http://www.cygwin.com/cygwin-ug-net/dll.html ale jak to louskám, tak asi potřebuju tu export library - zkouším ji vytvořit. Návody na C se špatně hledají, když to má jen jedno písmeno :-(

Výsledný program by měl fungovat s a i bez této dll. Jen by bez ni měl omezené funkce.

Nahlásit jako SPAM
IP: 90.176.59.–
etrix0
Newbie
13. 2. 2008   #6
-
0
-

Tak už jsem to asi vyřešil. Pokud by to někoho zajímalo, tady je řešení, které jsem pracně vykoumal, vygooglil a upravil tak, abych tomu i já rozumněl:

Vytvoření a volání externí dll v C (mingw, gcc)

dll.c:

#include <windows.h>


__declspec(dllexport) void WINAPI prvni_funkce(int a, int b) {
printf("-Prvni funkce- %i %i\n", a, b);
}

__declspec(dllexport) void WINAPI druha_funkce() {
printf("-Druha funkce-\n");
}


program.c:
 #include <windows.h>


typedef int (WINAPI * PRVNI_FUNKCE)(int, int);
typedef int (WINAPI * DRUHA_FUNKCE)(void);

main() {
HINSTANCE hLib=LoadLibrary("dll.dll");

if(hLib==NULL) {
printf("Unable to load library!\n");
getch();
return;
}

PRVNI_FUNKCE prvni_funkce=(PRVNI_FUNKCE)GetProcAddress(hLib, "prvni_funkce");
DRUHA_FUNKCE druha_funkce=(DRUHA_FUNKCE)GetProcAddress(hLib, "druha_funkce");

if((prvni_funkce==NULL) || (druha_funkce==NULL)) {

printf("Unable to load function(s).\n");
FreeLibrary(hLib);
getch();
return;
}

prvni_funkce(10, 20);
druha_funkce();

FreeLibrary(hLib);

getch();
}


Kompilace dll (vznikne dll.dll):
gcc -c dll.c

gcc -shared -Wl,--out-implib=libdll.dll.a -o dll.dll dll.o -Wl,--export-all-symbols
gcc -shared -o dll.dll dll.o -Wl,--kill-at,--output-def,dll.def
dlltool -d dll.def --dllname dll.dll --kill-at


Kompilace programu (vznikne program.exe)
gcc program.c -o program.exe


Výsledek po spuštění program.exe
-Prvni funkce- 10 20

-Druha funkce-


Pokud je tam nějaký vyložený nesmysl, tak mi prosím dejte vědět. Každopádně mi to funguje.

Nahlásit jako SPAM
IP: 90.176.59.–
AdamHlavatovic0
Stálý člen
13. 2. 2008   #7
-
0
-

toto vy nazivate prehladne vytvorenie a pouzitie dll kniznice ? :))

Nahlásit jako SPAM
IP: 217.73.16.–
etrix0
Newbie
13. 2. 2008   #8
-
0
-

To AdamHlavatovic : Máte pravdu, to vaše řešení je daleko lepší, udělám to podle vás.

Nahlásit jako SPAM
IP: 90.176.59.–
AdamHlavatovic0
Stálý člen
13. 2. 2008   #9
-
0
-

ziadne riesenie som schvalne neponukol, pretoze gcc nepouzivam a stoho dovodu vam nemozem poskitnut konkretny prikazovy riadok v zmysle gcc ...., nicmenej su mi zname 4 sposoby ako exportovat funkcie z dll kniznice a to:

ak kompilujete v c++ tak



extern "C" __declspec(dllexport) char * ce_foo(char * str)
{
static char s[40];
strncpy(s, str, 39);
s[39] = '\0';
return s;
}

ak kompilujete v c, tak


__declspec(dllexport) char * e_foo(char * str)
{
static char s[40];
strncpy(s, str, 39);
s[39] = '\0';
return s;
}

a treti a zaroven najprehladnejsi sposob je exportovat funkcie pomocou def suboru, takto
char * def_foo(char * str)

{
static char s[40];
strncpy(s, str, 39);
s[39] = '\0';
return s;
}

kde prislusny def subor bude vypadat nasledovne
LIBRARY	"dll"

EXPORTS
def_foo


no a stvrtym a zaroven mne poslednym znamim sposobom je sposob, ktory ste tu uviedol vy, tento sposob sa vyuziva v situaciach v ktorich je za behu programu potrebne zistit (ne)pritomnost funkcii, ktore neobsahuju vsetky podporovane verzie ms windows a teda tieto funkcie popripade emulovat vlastnym kodom (napr. funkcie win32 api ktore umoznuju vytvarat priehladne okna a ktore su podporovane len u win 2k+ napr. SetLayeredWindowAttributes a podobne.)

pre prpadnych zaujemcou uvadzam link na ukazku vytvorenia a pouzitia dll kniznice vo visual studiu http://www.mediafire.com/?4aehwmmtzny obsah prikazovych riadkou pre kompilator a linker uvadzat nebudem ale kazdy pripadny zaujemca si ich moze lahko zistit v Property Pages->C/C++->Command Line a v Property Pages->Linker->Command Line

pouzitie takto vytvorenej kniznice je potom nasledovne
#include <iostream>

#include "dll.h"
using std::cout;


int main(int argc, char * argv[])
{
char * str = "Frantova dll.";

// def file exported function
char * def_str = def_foo(str);
cout << "def_str: " << def_str << "\n";

// c++ export function
char * e_str = e_foo(str);
cout << "e_str: " << e_str << "\n";

// c export function
char * ce_str = ce_foo(str);
cout << "ce_str: " << ce_str << "\n";

system("pause");
return 0;
}

Nahlásit jako SPAM
IP: 217.73.16.–
etrix0
Newbie
13. 2. 2008   #10
-
0
-

Ještě jsem to upravil, protože původní řešení sice fungovalo, ale když jsem ho použil v hotovém projektu, tak program vždycky spadl s chybou ohledně "read memory". Pár hodin googlení a zkoušení nakonec pomohlo.
Spíš by mě teď zajímalo, proč to fungovalo bez "__declspec(dllexport) void WINAPI "...

Jinak návodů jak vytvořit dll v C++ atd. (MSVC, VB...) je na internetu hromada, kdežto za pomoci gcc moc ne. Kór když se jedná o dynamicky načítající dll. Různé návody všechno pletou dohromady a člověk se v tom potom špatně vyzná. Proto jsem chtěl přijít na přehledný příklad, jak udělat tuhle konkrétní věc, což se mi snad povedlo, pokud tam nebude nějaká zrada.
Každopádně každá rada může být přínosem.

Nahlásit jako SPAM
IP: 90.176.59.–
AdamHlavatovic0
Stálý člen
13. 2. 2008   #11
-
0
-

> Jinak návodů jak vytvořit dll v C++ ...
postup pre visual studio, pre c je uplne totozny ako mnou spominane, stym rozdielom ze subor pomenujete nieco.c namiesto nieco.cpp. Ostatne aj pre gcc je postup totozny ak pouzivate nejake IDE (napr. codeblocks).

Nahlásit jako SPAM
IP: 217.73.16.–
etrix0
Newbie
14. 2. 2008   #12
-
0
-

IDE nepoužívám.
Jen bych ještě potřeboval poradit jak funkce z dll použít i v jiných funkcích programu. V téhle ukázce používám funkce v té samé části, kde načítám dll. To funguje. Ale pokud chci funkce z dll použít i v jiné než v main() funkci, tak mi to hlásí chyby deklarace. A pokud použiju zase GetProcAddress, tak jto nezná hLib. Jak to vyřešit?

Nahlásit jako SPAM
IP: 90.176.59.–
Jura
~ Anonymní uživatel
634 příspěvků
14. 2. 2008   #13
-
0
-

To etrix :

No, buď si jednoduše uděláš globální proměnou nazvanou třeba g_hLib, kterou v main inicializuješ a pak už budeš jednoduše v těch funkcích načítat explictně funkce z DLL. Nebo čistější řešení, předávat těm funkcím jako parametr hLib. Nicméně bych dal přednost naprosto jinému používání dll, než to takhle explictně načítat. (Viz výše)

Nahlásit jako SPAM
IP: 85.207.192.–
etrix0
Newbie
17. 2. 2008   #14
-
0
-

To Jura : Dík, funguje to. Ale měl bych další dotaz, proč nemůžu použít:

if (podminka_A) {

PRVNI_FUNKCE prvni_funkce=(PRVNI_FUNKCE)GetProcAddress(hLib, "prvni_funkce");
}

if (podminka_A) {
prvni_funkce();
}


Píše mi to "warning: unused variable `prvni_funkce'", ale když to sloučím do jedné podmíky, tak to funguje. Čím by to mohlo být? Jde mi o to, že podminka_A zjišťuje, jestli je knihovna načtena a pokud ano, vezme se z ní funkce. Ve druhé podmínce se použije. A druhá podmínka je zároveň ve smyčce, takže bych rád exportoval funkci jen jednou a ve smyčce opakovaně použil, místo toho abych ji ve smyčce tisíckrát exportoval a používal, když exportnout by měla stačit jednou.

Nahlásit jako SPAM
IP: 90.176.59.–
Jura
~ Anonymní uživatel
634 příspěvků
17. 2. 2008   #15
-
0
-



PRVNI_FUNKCE prvni_funkce;
if (podminka_A) {
prvni_funkce=(PRVNI_FUNKCE)GetProcAddress(hLib, "prvni_funkce");
}

if (podminka_A) {
prvni_funkce();
}

Nahlásit jako SPAM
IP: 85.207.192.–
AdamHlavatovic0
Stálý člen
17. 2. 2008   #16
-
0
-

To etrix : Stohto vášho dotazu je zrejmé, že nemáte dostatočne naštudované základy jazyka c, c++. Váš kus kódu nefunguje preto, lebo premenná prvni_funkce je v druhej podmienke neznáma, tj. zaniká s ukončením bloku v prvej podmienke.

Nahlásit jako SPAM
IP: 217.73.16.–
etrix0
Newbie
18. 2. 2008   #17
-
0
-

To Jura : Díky, jak prosté.

To AdamHlavatovic : Víte, kdybych ty základy měl, tak se tady neptám a nevím co to má společného s dotazem. To, že programovací jazyk C uchovává proměnné i jen v pouze v podmínkách, namísto v celých funkcích, je pro mě novinka, o které jsem dodnes ještě nikdy neslyšel ani zmínku.

Nahlásit jako SPAM
IP: 90.176.59.–
AdamHlavatovic0
Stálý člen
18. 2. 2008   #18
-
0
-

> To, že programovací jazyk C uchovává proměnné i jen v pouze v podmínkách, namísto v celých funkcích ...
Premenné v jazyku c, c++ deklarované „štandardným“ spôsobom (tj. bez niektorého s modifikátorov) majú tzv. lokálnu platnosť, ktorá začína samotnou deklaráciou premennej a končí koncom bloku v ktorom bola premenná deklarovaná, napr.



{
...
{
int franta = 10;
...
franta = 5; // v poriadku premenna franta existuje
} // koncom bloku zanika platnost premennej franta

franta = 15; // chyba, premenna franta neexistuje
}

> Víte, kdybych ty základy měl, tak se tady neptám a nevím co to má společného s dotazem.
Mojou reakciou na váš dotaz, som sa vám snažil decentne naznačiť, že by ste sa mal oboznámiť aspoň s elementárnymi základmi jazyka v ktorom chcete pracovať.

Nahlásit jako SPAM
IP: 217.73.16.–
Svatik
~ Anonymní uživatel
2 příspěvky
3. 3. 2008   #19
-
0
-

To etrix : Tvůj problém je instalace Dev C++ nainstaluj si to a nepotřebuješ Visual Studio.

Nahlásit jako SPAM
IP: 89.24.249.–
Svatik
~ Anonymní uživatel
2 příspěvky
3. 3. 2008   #20
-
0
-

Zadej v conzoli GCC přepinač --target-help nebo tak nějak

Nahlásit jako SPAM
IP: 89.24.249.–
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, 94 hostů

Podobná vlákna

C# - pouziti += — založil aleskm

C# použití linq — založil Marek

Použití výjimek v C++ — založil Jonyzz

Použití GUI — založil Nicolas

Použití iconv() — založil jumi

Moderátoři diskuze

 

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