(Einfachste) DLLs erstellen und einbinden
-
Ich habe mir mittels des DLL Templates von Code::Blocks eine kleine DLL mit folgendem Code erstellt, der sich auch problemlos kompilieren lässt (es entstehen eine .dll und eine .a):
#include <iostream> using namespace std; #ifdef BUILD_DLL #define DLL_EXPORT __declspec(dllexport) #else #define DLL_EXPORT #endif void DLL_EXPORT hallo() { cout<<"Hallo Welt"<<endl; }Ich habe noch nie mit Präprozessorbefehlen gearbeitet und verstehe daher diese Zeilen nicht (bitte erklären wenn möglich). Aber das ist nicht meine eigentliche Frage. Diese lautet - Wie binde ich diese wunderhübsche DLL in ein weiteres normales Projekt ein und wie rufe ich die Funktion hallo() auf, sodass auf dem Bildschirm der Text "Hallo Welt" erscheint?
-
Eigentlich besteht so ein projekt (mindestens) aus header und cpp. Im Header steht dann sowas hier:
#ifdef BUILD_DLL #define DLL_EXPORT __declspec(dllexport) #else #define DLL_EXPORT #endif void DLL_EXPORT hallo();im cpp sowas:
#include "header.h" void DLL_EXPORT hall() { cout << "hallo" << endl; }Der Header wird überall eingebunden, wo du die Funktionen aus der DLL benutzen willst. Wenn die dll kompiliert und gelinkt wird, dann hat code::blocks automatisch dem gcc ein -DBUILD_DLL mitegeben. Also ist BUILD_DLL definiert, wenn die DLl gebaut wird. Damit expandiert DLL_EXPORT zu __declspec(dllexport). D.h. deine DLL macht alle Funktionen/Objekte/sontwas die mit dem Makro DLL_EXPORT ausgezeichnet sind öffneltich, sodass andere sie benutzen können.
Wenn du jetzt in dein anderen Projekt den header einbindest, ist BUILD_DLL nicht definiert, also wird DLL_EXPORT zu nichts expandiert, denn dein hauptrojekt exportiert ja ncihts in eine DLL sondern benutzt nur die Funktion. Dazu die präprozessorbefehle.So, zu einbindung: wie gesagt, im hauptorgramm den header einbinden und kompilieren. Kompilieren tut er dann, linken nicht. Er sagt nämlich, dass er nicht weiß was hallo() denn ist (also unresolved external symbol). Deshalb musst du im Hauptprogramm noch die .a einbinden. Die sagt dem Linker, dass er beim programmstart die dll laden muss, denn da steht deine funktion hallo() drin und alles müsste funktionieren.
-
zu deiner zweten frage:
Du erzeugst ganz normal ein projekt. Einbinden: Du hast die header deiner dll (Deklarationen der schnittstelle), die kannst du includieren.
Damit die referenzen korrekt aufgelöst werden, gibt es die .a oder .lib datei. Die linkst du ganz normal zu deinem programm, wie eine statische lib (linker settings). Dann sollten die Codes aus der DLL aufgerufen werden.erste frage:
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)bedeutet, wenn BUILD_DLL gesetzt ist (build options, #defines), dann wird DLL_EXPORT als __declspec(dllexport) definiert. __declspec(dllexport) muss vor funktionen die exportiert werden sollen, geschrieben werden:
__declspec(dllexport) int test();bei klassen
class __declspec(dllexport) klasse;damit du nicht jedes mal __declspec(dllexport) schreiben musst, wird das makri definiert.
wenn dann mal keine DLL gebaut werden soll aus den codes, dann ist DLL_EXPORT definiert und wird durch "" ersetzt und stört nicht weiter.-edit-
da war einer schneller
-
es klappt - vielen dank
p.s.: kann mir villeicht jemand sagen, was die Fehlermeldung
warning: no newline at end of file bedeutet ? Jedenfalls nicht das was sie übersetzt bedeutet ^^
-
Ganz einfach, es fehlt eine Leerzeile am Ende der Datei

-
und warum verursacht das ne Warnung? ->

-
Weil der Standard eben einfach will dass eine Zeile mit Newline abgeschlossen wird. Auch die letzte.
-
Und wie bindet man dll's ein deren .a's man nicht hat?
-
über LoadLibrary(), dann hast du aber den Nachteil, dass du auf keine Klassen zugreifen kannst.
nur Variablen und Funktionen.
-
und wie ginge das mit meiner oben genannten dll?
-
dann musst du deine funktion erstmal in einen extern "C" Block hauen.
// header extern "C" { int __declspec(dllexport) hallo(); } // cpp int hallo() { return 1; }und im hauptorgramm dann so:
HMODULE dll = LoadLibrary("Deinedll-datei.dll"); typedef int(*fn)(); // Funktionszeigertyp fn zeiger_auf_deine_funktion = (fn)GetProcAddress(dll, "hallo"); cout << zeiger_auf_deine_funktion() << endl;So kurz gesagt. Jedenfalls mit loadlibrary und getprocaddress. Das extern "C" muss sein, wei lder C++-Compiler sonst name-mangeling anwendet, also er verschlüsselt deine funktionsnamen, damit man auch überladene funktionen schreiben kann, was in extern "C" nicht geht. Dafür heißt deine funktion aber auch so, wie du sie nennst und nciht mit kryptischen @ und so drin.
[/cpp]
-
Main.cpp:
#include <windows.h> typedef void (*hallo_ptr)(void); int main() { HMODULE dll_handle = LoadLibrary("deine.dll"); hallo_ptr hallo_fn = (hallo_ptr)GetProcAddress(dll_handle, "hallo"); (hallo_fn)(); FreeLibrary(dll_handle); }hallo.cpp:
#include <iostream> using namespace std; #ifdef BUILD_DLL #define DLL_EXPORT __declspec(dllexport) #else #define DLL_EXPORT #endif extern "C" //C++ Name-Mangling umgehen { void DLL_EXPORT hallo() { cout<<"Hallo Welt"<<endl; } }Grüße,
Martin
EDIT: Da war jemand schneller

-
Sag mal, wir sind hier im C++-Forum und nicht im WinAPI-Forum...
-
geht es auch ohne winapi?
-
Falls du damit meinst, mit der Standard-C++ Library: nein
AFAIK bietet aber z.B. wxWidgets Funktionen zum platformunabhängigen Laden von dynamischen Bibliotheken an...Grüße,
Martin
-
findet man denn zu den meisten dll's die dazu passenden .a's und header dateien?
-
Das kommt darauf an: Wenn die DLL dazu gedacht ist, von dir verwendet zu werden, und du sie nicht einfach aus irgendeinem Programm klaust, sollte in jedem Fall irgendeine Form von Importbibliothek beiligen. Kann halt passieren, dass dort keine Bibliotheken für den GCC beiligen, sondern nur für MS-VC++ oder BCB, keine Ahnung, ob es Tools gibt, die diese entsprechend umwandeln können.
Fein raus bist du, wenn es sich um OpenSource Bibliotheken handelt, da diese meist direkt für den GCC entwickelt wurden und, falls nicht schon Binaries beiligen, unkompliziert gebaut werden können.
Header liegen in jedem Fall bei, da du die Bibliothek ja sonst überhaupt nicht verwenden kannst...Grüße,
Martin
-
Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum WinAPI verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
alfonsospringer schrieb:
geht es auch ohne winapi?
lol
