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?
Fórum › C / C++
Použití dll v C
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;)
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: ...".
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).
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.
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.
toto vy nazivate prehladne vytvorenie a pouzitie dll kniznice ? :))
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;
}
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.
> 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).
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?
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)
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.
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.
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.
> 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ť.
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Nenašly se knihovny tbb.dll a tbb_debug.dll — založil Kevil
Import dll do me dll — založil VladislavK
C# - pouziti += — založil aleskm
Moderátoři diskuze