Λόγω της ραγδαίας ανάπτυξης των τεχνολογιών προγραμματισμού, όλο και περισσότεροι άνθρωποι αντιμετωπίζουν το πρόβλημα της αύξησης των δυνατοτήτων των προγραμμάτων τους. Αυτό το άρθρο είναι αφιερωμένο σε αυτό το ζήτημα, δηλαδή στον προγραμματισμό DLL στο Borland Delphi. Επιπλέον, καθώς θα θίξουμε τα ζητήματα χρήσης DLL, θα θίξουμε και την εισαγωγή συναρτήσεων από DLL άλλων ατόμων (συμπεριλαμβανομένων των συστημάτων, π.χ. WinAPI).

Εφαρμογές DLL

Λοιπόν, γιατί χρειάζονται τα DLL και πού χρησιμοποιούνται;.. Ακολουθούν μερικοί από τους τομείς εφαρμογής τους:

  • Ξεχωριστές Βιβλιοθήκες, που περιέχει πρόσθετες λειτουργίες χρήσιμες για προγραμματιστές. Για παράδειγμα, συναρτήσεις για εργασία με συμβολοσειρές ή σύνθετες βιβλιοθήκες για μετατροπή εικόνων.
  • Καταστήματα πόρων. Σε ένα DLL, μπορείτε να αποθηκεύσετε όχι μόνο προγράμματα και λειτουργίες, αλλά και όλα τα είδη πόρων - εικονίδια, εικόνες, συστοιχίες συμβολοσειρών, μενού κ.λπ.
  • Υποστήριξη Βιβλιοθηκών. Ένα παράδειγμα είναι οι βιβλιοθήκες γνωστών πακέτων όπως: DirectX, ICQAPI(API για ICQ), OpenGLκαι τα λοιπά.
  • Μέρη του προγράμματος. Για παράδειγμα, ένα DLL μπορεί να αποθηκεύσει παράθυρα προγραμμάτων (φόρμες) κ.λπ.
  • Πρόσθετα(Πρόσθετα). - Εκεί είναι το πραγματικό περιθώριο για τις σκέψεις του προγραμματιστή! Τα πρόσθετα είναι προσθήκες στο πρόγραμμα που διευρύνουν τις δυνατότητές του. Για παράδειγμα, σε αυτό το άρθρο θα εξετάσουμε τη θεωρία της δημιουργίας ενός πρόσθετου για το δικό σας πρόγραμμα.
  • Κοινόχρηστος πόρος. DLL( Βιβλιοθήκη Dynamic Link) μπορεί να χρησιμοποιηθεί από πολλά προγράμματα ή διαδικασίες ταυτόχρονα (τα λεγόμενα. μοιρασιά- κοινόχρηστος πόρος)

Σύντομη περιγραφή λειτουργιών και κόλπα για εργασία με DLL

Λοιπόν, ποια κόλπα και λειτουργίες πρέπει να χρησιμοποιήσετε για να εργαστείτε με ένα DLL; Ας αναλύσουμε δύο μεθόδους για την εισαγωγή συναρτήσεων από τη βιβλιοθήκη:

1 τρόπος. Σύνδεση ενός DLL σε ένα πρόγραμμα.Αυτή είναι η απλούστερη και ευκολότερη μέθοδος για τη χρήση συναρτήσεων που εισάγονται από ένα DLL. Ωστόσο (και πρέπει να δώσετε προσοχή σε αυτό) αυτή η μέθοδος έχει ένα πολύ σημαντικό μειονέκτημα - εάν δεν βρεθεί η βιβλιοθήκη που χρησιμοποιεί το πρόγραμμα, τότε το πρόγραμμα απλά δεν θα ξεκινήσει, δίνοντας ένα σφάλμα και αναφέροντας ότι ο πόρος DLL δεν βρέθηκε. Και θα γίνει αναζήτηση στη βιβλιοθήκη: στον τρέχοντα κατάλογο, στον κατάλογο του προγράμματος, στον κατάλογο WINDOWS\SYSTEM κ.λπ.
Έτσι, για αρχάριους - η γενική μορφή αυτής της τεχνικής:

εκτέλεση
...
λειτουργία FunctionName(Par1: Par1Type; Par2: Par2Type; ...): ReturnType; stdcall; εξωτερικός"DLLNAME.DLL" όνομα"Όνομα συνάρτησης" δείκτης FuncIndex;
// ή (αν όχι συνάρτηση, αλλά διαδικασία):
διαδικασία ProcedureName(Par1: Par1Type; Par2: Par2Type; ...); stdcall; εξωτερικός"DLLNAME.DLL" όνομα"όνομα διαδικασίας" δείκτης ProcIndex;

Εδώ: Όνομα συνάρτησηςΌνομα διαδικασίας) - το όνομα της συνάρτησης (ή της διαδικασίας) που θα χρησιμοποιηθεί στο πρόγραμμά σας.
Par1, Par2, ...- ονόματα παραμέτρων συνάρτησης ή διαδικασίας.
Par1Type, Par2Type, ...- τύποι παραμέτρων μιας συνάρτησης ή μιας διαδικασίας (για παράδειγμα, Ακέραιος αριθμός);
τύπος επιστροφής- τύπος τιμής επιστροφής (μόνο για μια συνάρτηση).
stdcall- μια οδηγία που πρέπει να ταιριάζει ακριβώς με αυτή που χρησιμοποιείται στο ίδιο το DLL.
εξωτερικό "DLLNAME.DLL"- μια οδηγία που καθορίζει το όνομα του εξωτερικού DLL από το οποίο θα εισαχθεί η δεδομένη λειτουργία ή διαδικασία (στην περίπτωση αυτή - DLLNAME.DLL);
όνομα "FunctionName" ("ProcedureName")- μια οδηγία που καθορίζει το ακριβές όνομα μιας συνάρτησης στο ίδιο το DLL. Αυτή είναι μια προαιρετική οδηγία που σας επιτρέπει να χρησιμοποιήσετε μια συνάρτηση στο πρόγραμμα που έχει όνομα διαφορετικό από το αληθινό (το οποίο έχει στη βιβλιοθήκη).
ευρετήριο FunctionIndex(ProcedureIndex)- μια οδηγία που καθορίζει τον τακτικό αριθμό μιας συνάρτησης ή μιας διαδικασίας σε ένα DLL. Αυτή είναι επίσης μια προαιρετική οδηγία.

2 τρόπος. Δυναμική φόρτωση DLL.Αυτή είναι μια πολύ πιο σύνθετη αλλά και πιο κομψή μέθοδος. Δεν έχει το μειονέκτημα της πρώτης μεθόδου. Το μόνο που είναι δυσάρεστο είναι η ποσότητα του κώδικα που απαιτείται για την υλοποίηση αυτής της τεχνικής και η δυσκολία είναι ότι η συνάρτηση που εισάγεται από το DLL είναι διαθέσιμη μόνο όταν αυτό το DLL είναι φορτωμένο και βρίσκεται στη μνήμη... Μπορείτε να διαβάσετε το παρακάτω παράδειγμα, αλλά προς το παρόν - μια σύντομη περιγραφή των συναρτήσεων WinAPI που χρησιμοποιούνται από αυτήν τη μέθοδο:

Φόρτωση Βιβλιοθήκης(libfilename: PCχαρ) - φόρτωση της καθορισμένης βιβλιοθήκης LibFileName στη μνήμη. Με επιτυχία, η συνάρτηση επιστρέφει μια λαβή ( THandle) DLL στη μνήμη.
GetProcAddress(Μονάδα μέτρησης: THandle; ProcName: PCχαρ) - διαβάζει τη διεύθυνση της εξαγόμενης συνάρτησης βιβλιοθήκης. Με επιτυχία, η συνάρτηση επιστρέφει μια λαβή ( TFarProc) λειτουργεί στο φορτωμένο DLL.
ελεύθερη βιβλιοθήκη(LibModule: THandle) - ακυρώνει το LibModule και ελευθερώνει τη μνήμη που σχετίζεται με αυτό. Θα πρέπει να σημειωθεί ότι μετά την κλήση αυτής της διαδικασίας, οι λειτουργίες αυτής της βιβλιοθήκης δεν είναι πλέον διαθέσιμες.

Πρακτική και παραδείγματα

Λοιπόν, τώρα ήρθε η ώρα να δώσουμε μερικά παραδείγματα χρήσης των παραπάνω μεθόδων και τεχνικών:

Τώρα το ίδιο πράγμα, αλλά με τον δεύτερο τρόπο - με δυναμική φόρτωση:

(... Εδώ έρχεται η κεφαλίδα του αρχείου και ο ορισμός της φόρμας TForm1 και της παρουσίας της Form1)

var
Form1: TForm1;
GetSimpleText: λειτουργία(LangRus: Boolean): PChar;
LibHandle: THandle;

διαδικασία Button1Click(Αποστολέας: TObject);
να αρχίσει
("Καθαρίζουμε" τη διεύθυνση της λειτουργίας από "βρωμιά")
@GetSimpleText:= μηδέν;
(Προσπαθώ να φορτώσω τη βιβλιοθήκη)
LibHandle:= LoadLibrary("MYDLL.DLL");
(Αν όλα είναι εντάξει)
αν LibHandle >= 32 τότε ξεκινήστε
(... τότε προσπαθούμε να πάρουμε τη διεύθυνση της συνάρτησης στη βιβλιοθήκη)
@GetSimpleText:= GetProcAddress(LibHandle,"GetSimpleText");
(Αν όλα είναι εντάξει εδώ)
εάν @GetSimpleText<>μηδέν τότε
(... τότε καλούμε αυτή τη συνάρτηση και δείχνουμε το αποτέλεσμα)
ShowMessage(StrPas(GetSimpleText(True)));
τέλος;
(Και μην ξεχάσετε να ελευθερώσετε τη μνήμη και να ξεφορτώσετε το DLL)
FreeLibrary(LibHandle);
τέλος;

ΣΗΜΕΙΩΣΗ : Θα πρέπει να αποφύγετε τη χρήση του τύπου συμβολοσειράς στις συναρτήσεις της βιβλιοθήκης, γιατί υπάρχουν προβλήματα με την "κοινή χρήση μνήμης" κατά τη χρήση του. Μπορείτε να διαβάσετε περισσότερα για αυτό (αν και στα Αγγλικά) στο κείμενο του άδειου έργου DLL που δημιουργεί η Delphi (Αρχείο -> Νέο -> DLL). Επομένως, είναι καλύτερο να χρησιμοποιήσετε το PChar και στη συνέχεια να το μετατρέψετε σε συμβολοσειρά με StrPas εάν είναι απαραίτητο.

Λοιπόν, τώρα ας αναλύσουμε απευθείας το ίδιο το DLL:

Τοποθέτηση σε πόρους και φόρμες DLL

Σε ένα DLL, μπορείτε να τοποθετήσετε όχι μόνο λειτουργίες, αλλά και δρομείς, εικόνες, εικονίδια, μενού, γραμμές κειμένου. Δεν θα σταθούμε σε αυτό. Θα σημειώσω μόνο ότι για να φορτώσετε τον πόρο, πρέπει να φορτώσετε το DLL και, στη συνέχεια, έχοντας λάβει τον περιγραφέα του, φορτώστε τον ίδιο τον πόρο με την κατάλληλη συνάρτηση (LoadIcon, LoadCursor, κ.λπ.). Σε αυτήν την ενότητα, θα θίξουμε μόνο εν συντομία την τοποθέτηση των παραθύρων εφαρμογών (δηλ. φορμών στους Δελφούς) σε DLL.

Για να το κάνετε αυτό, πρέπει να δημιουργήσετε ένα νέο DLL και να προσθέσετε μια νέα φόρμα σε αυτό (Αρχείο -> Νέο -> DLL και μετά Αρχείο -> Νέα φόρμα). Επιπλέον, εάν η φόρμα είναι ένα πλαίσιο διαλόγου (τροπική φόρμα (bsDialog)), τότε προσθέστε την ακόλουθη συνάρτηση στο DLL (για παράδειγμα, η φόρμα ονομάζεται Form1 και η κλάση της είναι TForm1):

Εάν πρέπει να τοποθετήσετε μια μη-τροπική φόρμα στο DLL, τότε πρέπει να κάνετε δύο λειτουργίες - άνοιγμα και κλείσιμο της φόρμας. Σε αυτήν την περίπτωση, πρέπει να αναγκάσετε το DLL να θυμάται τη λαβή σε αυτήν τη φόρμα.

Δημιουργία πρόσθετων

Εδώ δεν θα εξετάσουμε λεπτομερώς τα πρόσθετα, γιατί. Τα παραδείγματα που έχουν ήδη δοθεί παραπάνω θα σας βοηθήσουν να κατανοήσετε εύκολα τη μερίδα του λέοντος στον προγραμματισμό DLL. Να σας υπενθυμίσω μόνο ότι το plug-in είναι μια προσθήκη στο πρόγραμμα που επεκτείνει τις δυνατότητές του. Ταυτόχρονα, το ίδιο το πρόγραμμα πρέπει απαραίτητα να προβλέπει την παρουσία τέτοιων προσθηκών και να τους επιτρέπει να εκπληρώσουν το σκοπό τους.

Δηλαδή, για παράδειγμα, για να δημιουργήσετε ένα πρόσθετο για ένα πρόγραμμα επεξεργασίας γραφικών που θα εκτελούσε μετατροπή εικόνας, πρέπει να παρέχετε τουλάχιστον δύο λειτουργίες στο πρόσθετο (και, κατά συνέπεια, να καλέσετε αυτές τις λειτουργίες στο πρόγραμμα) - μια συνάρτηση που θα επέστρεφε το όνομα της προσθήκης (ή/και τον τύπο της) για να προσθέσετε αυτήν την προσθήκη στο μενού (ή στη γραμμή εργαλείων), συν η κύρια λειτουργία είναι η αποστολή και λήψη μιας εικόνας. Εκείνοι. πρώτα, το πρόγραμμα αναζητά πρόσθετα, στη συνέχεια για κάθε ένα που βρέθηκε καλεί τη συνάρτηση αναγνώρισής του με ένα αυστηρά καθορισμένο όνομα (για παράδειγμα, GetPluginName) και προσθέτει το επιθυμητό στοιχείο στο μενού και, στη συνέχεια, εάν ο χρήστης έχει επιλέξει αυτό το στοιχείο, καλεί η δεύτερη συνάρτηση, η οποία μεταβιβάζει την εικόνα εισόδου (ή το όνομα αρχείου που περιέχει αυτήν την εικόνα) και αυτή η συνάρτηση, με τη σειρά της, επεξεργάζεται την εικόνα και την επιστρέφει σε νέα μορφή (ή όνομα αρχείου με νέα εικόνα). Αυτό είναι όλο το νόημα του πρόσθετου... :-)

Επίλογος

Αυτό το άρθρο δείχνει τις κύριες πτυχές χρήσης και δημιουργίας DLL στο Borland Delphi. Εάν έχετε οποιεσδήποτε ερωτήσεις - στείλτε τις σε μένα μέσω e-mail: [email προστατευμένο], και ακόμα καλύτερα - γράψτε στο συνέδριο αυτού του ιστότοπου ώστε οι άλλοι χρήστες να δουν την ερώτησή σας και να προσπαθήσουν να την απαντήσουν!

Karikh Nikolai. Περιοχή της Μόσχας, Ζουκόφσκι


Λόγω της ραγδαίας ανάπτυξης των τεχνολογιών προγραμματισμού, όλο και περισσότεροι άνθρωποι αντιμετωπίζουν το πρόβλημα της αύξησης των δυνατοτήτων των προγραμμάτων τους. Αυτό το άρθρο είναι αφιερωμένο σε αυτό το ζήτημα, δηλαδή στον προγραμματισμό DLL στο Borland Delphi. Επιπλέον, καθώς θα θίξουμε τα ζητήματα χρήσης DLL, θα θίξουμε και την εισαγωγή συναρτήσεων από DLL άλλων ατόμων (συμπεριλαμβανομένων των συστημάτων, π.χ. WinAPI).

Εφαρμογές DLL

Λοιπόν, γιατί χρειάζονται τα DLL και πού χρησιμοποιούνται;.. Ακολουθούν μερικοί από τους τομείς εφαρμογής τους:

Ξεχωριστές βιβλιοθήκες που περιέχουν πρόσθετες λειτουργίες χρήσιμες για προγραμματιστές.

Για παράδειγμα, συναρτήσεις για εργασία με συμβολοσειρές ή σύνθετες βιβλιοθήκες για μετατροπή εικόνων.

Καταστήματα πόρων. Σε ένα DLL, μπορείτε να αποθηκεύσετε όχι μόνο προγράμματα και λειτουργίες, αλλά και όλα τα είδη πόρων - εικονίδια, εικόνες, συστοιχίες συμβολοσειρών, μενού κ.λπ.

Υποστήριξη Βιβλιοθηκών. Ένα παράδειγμα είναι οι βιβλιοθήκες γνωστών πακέτων όπως: DirectX, ICQAPI (API για ICQ), OpenGL κ.λπ.

Μέρη του προγράμματος. Για παράδειγμα, ένα DLL μπορεί να αποθηκεύσει παράθυρα προγραμμάτων (φόρμες) κ.λπ.

Πρόσθετα. - Εκεί είναι το πραγματικό περιθώριο για τις σκέψεις του προγραμματιστή! Τα πρόσθετα είναι προσθήκες στο πρόγραμμα που διευρύνουν τις δυνατότητές του. Για παράδειγμα, σε αυτό το άρθρο θα εξετάσουμε τη θεωρία της δημιουργίας ενός πρόσθετου για το δικό σας πρόγραμμα.

Κοινόχρηστος πόρος. Το DLL (Βιβλιοθήκη Dynamic Link) μπορεί να χρησιμοποιηθεί από πολλά προγράμματα ή διεργασίες ταυτόχρονα (η λεγόμενη κοινή χρήση είναι ένας κοινόχρηστος πόρος)

Σύντομη περιγραφή λειτουργιών και κόλπα για εργασία με DLL

Λοιπόν, ποια κόλπα και λειτουργίες πρέπει να χρησιμοποιήσετε για να εργαστείτε με ένα DLL; Ας αναλύσουμε δύο μεθόδους για την εισαγωγή συναρτήσεων από τη βιβλιοθήκη:

1 τρόπος. Σύνδεση ενός DLL σε ένα πρόγραμμα. Αυτή είναι η απλούστερη και ευκολότερη μέθοδος για τη χρήση συναρτήσεων που εισάγονται από ένα DLL. Ωστόσο (και θα πρέπει να δώσετε προσοχή σε αυτό) αυτή η μέθοδος έχει ένα πολύ σημαντικό μειονέκτημα - εάν δεν βρεθεί η βιβλιοθήκη που χρησιμοποιεί το πρόγραμμα, τότε το πρόγραμμα απλά δεν θα ξεκινήσει, δίνοντας ένα σφάλμα και αναφέροντας ότι ο πόρος DLL δεν βρέθηκε. Και θα γίνει αναζήτηση στη βιβλιοθήκη: στον τρέχοντα κατάλογο, στον κατάλογο του προγράμματος, στον κατάλογο WINDOWSSYSTEM κ.λπ.

Έτσι, για αρχάριους - η γενική μορφή αυτής της τεχνικής:

Εκτέλεση
...
συνάρτηση FunctionName(Par1: Par1Type; Par2: Par2Type; ...): ReturnType; stdcall; εξωτερικό "DLLNAME.DLL" όνομα Ευρετήριο "FunctionName" FuncIndex;
// ή (αν όχι συνάρτηση, αλλά διαδικασία):
διαδικασία ProcedureName(Par1: Par1Type; Par2: Par2Type; ...); stdcall; εξωτερικό "DLLNAME.DLL" όνομα Ευρετήριο "ProcedureName" ProcIndex.

Εδώ: FunctionName (ή ProcedureName) - το όνομα της συνάρτησης (ή της διαδικασίας) που θα χρησιμοποιηθεί στο πρόγραμμά σας.

Par1, Par2, ... - ονόματα παραμέτρων συνάρτησης ή διαδικασίας.
Par1Type, Par2Type, ...- τύποι παραμέτρων μιας συνάρτησης ή μιας διαδικασίας (για παράδειγμα, Ακέραιος).
τύπος επιστροφής- τύπος τιμής επιστροφής (μόνο για μια συνάρτηση).
stdcall- μια οδηγία που πρέπει να ταιριάζει ακριβώς με αυτή που χρησιμοποιείται στο ίδιο το DLL.
εξωτερικό "DLLNAME.DLL"- μια οδηγία που καθορίζει το όνομα του εξωτερικού DLL από το οποίο θα εισαχθεί η συγκεκριμένη λειτουργία ή διαδικασία (στην περίπτωση αυτή, DLLNAME.DLL).
όνομα "FunctionName"("ProcedureName") είναι μια οδηγία που καθορίζει το ακριβές όνομα μιας συνάρτησης στο ίδιο το DLL.

Αυτή είναι μια προαιρετική οδηγία που σας επιτρέπει να χρησιμοποιήσετε μια συνάρτηση στο πρόγραμμα που έχει όνομα διαφορετικό από το αληθινό (το οποίο έχει στη βιβλιοθήκη).
ευρετήριο FunctionIndex (ProcedureIndex) - μια οδηγία που καθορίζει τον τακτικό αριθμό μιας συνάρτησης ή μιας διαδικασίας σε ένα DLL. Αυτή είναι επίσης μια προαιρετική οδηγία.

2 τρόπος. Δυναμική φόρτωση DLL. Αυτή είναι μια πολύ πιο σύνθετη αλλά και πιο κομψή μέθοδος. Δεν έχει το μειονέκτημα της πρώτης μεθόδου. Το μόνο που είναι δυσάρεστο είναι η ποσότητα του κώδικα που απαιτείται για την υλοποίηση αυτής της τεχνικής και η δυσκολία είναι ότι η συνάρτηση που εισάγεται από το DLL είναι διαθέσιμη μόνο όταν αυτό το DLL είναι φορτωμένο και βρίσκεται στη μνήμη... Μπορείτε να διαβάσετε το παρακάτω παράδειγμα, αλλά προς το παρόν - μια σύντομη περιγραφή των συναρτήσεων WinAPI που χρησιμοποιούνται από αυτήν τη μέθοδο:

Φόρτωση Βιβλιοθήκης(LibFileName: PChar) - φόρτωση της καθορισμένης βιβλιοθήκης LibFileName στη μνήμη. Με επιτυχία, η συνάρτηση επιστρέφει μια λαβή (THandle) στο DLL στη μνήμη.
GetProcAddress(Module: THandle ; ProcName: PChar) - διαβάζει τη διεύθυνση μιας εξαγόμενης λειτουργίας βιβλιοθήκης. Σε περίπτωση επιτυχίας, η συνάρτηση επιστρέφει μια λαβή (TFarProc) στη συνάρτηση στο φορτωμένο DLL.
ελεύθερη βιβλιοθήκη(LibModule: THandle) - Ακυρώνει το LibModule και ελευθερώνει τη μνήμη που σχετίζεται με αυτό. Θα πρέπει να σημειωθεί ότι μετά την κλήση αυτής της διαδικασίας, οι λειτουργίες αυτής της βιβλιοθήκης δεν είναι πλέον διαθέσιμες.

Πρακτική και παραδείγματα

Λοιπόν, τώρα ήρθε η ώρα να δώσουμε μερικά παραδείγματα χρήσης των παραπάνω μεθόδων και τεχνικών: Παράδειγμα 1. Σύνδεση ενός DLL σε ένα πρόγραμμα

Εκτέλεση

(Ορισμός μιας λειτουργίας εξωτερικής βιβλιοθήκης)

Συνάρτηση GetSimpleText(LangRus: Boolean): PChar; stdcall; εξωτερικό "MYDLL.DLL"?


να αρχίσει
(και χρησιμοποιήστε το)
ShowMessage(StrPas(GetSimpleText(False)));
(ShowMessage - εμφανίζει ένα πλαίσιο διαλόγου με την καθορισμένη λεζάντα, StrPas - μετατρέπει μια συμβολοσειρά PChar σε συμβολοσειρά)
τέλος;

Τώρα το ίδιο πράγμα, αλλά με τον δεύτερο τρόπο - με δυναμική φόρτωση: Παράδειγμα 2. Δυναμική φόρτωση ενός DLL

(... Εδώ έρχεται η κεφαλίδα του αρχείου και ο ορισμός της φόρμας TForm1 και της παρουσίας της Form1)

Var
Form1: TForm1;
GetSimpleText: συνάρτηση (LangRus: Boolean): PChar;
LibHandle: THandle;

ProcedureButton1Click(Αποστολέας: TObject);
να αρχίσει
("Καθαρίζουμε" τη διεύθυνση της λειτουργίας από "βρωμιά")
@GetSimpleText:= μηδέν;
(Προσπαθώ να φορτώσω τη βιβλιοθήκη)
LibHandle:= LoadLibrary("MYDLL.DLL");
(Αν όλα είναι εντάξει)
αν LibHandle >= 32 τότε ξεκινήστε
(... τότε προσπαθούμε να πάρουμε τη διεύθυνση της συνάρτησης στη βιβλιοθήκη)
@GetSimpleText:= GetProcAddress(LibHandle,"GetSimpleText");
(Αν όλα είναι εντάξει εδώ)
αν @GetSimpleText μηδενιστεί τότε
(... τότε καλούμε αυτή τη συνάρτηση και δείχνουμε το αποτέλεσμα)
ShowMessage(StrPas(GetSimpleText(True)));
τέλος;
(Και μην ξεχάσετε να ελευθερώσετε τη μνήμη και να ξεφορτώσετε το DLL)
FreeLibrary(LibHandle);
τέλος;

ΣΗΜΕΙΩΣΗ: Θα πρέπει να αποφύγετε τη χρήση του τύπου συμβολοσειράς στις συναρτήσεις της βιβλιοθήκης, γιατί υπάρχουν προβλήματα με την "κοινή χρήση μνήμης" κατά τη χρήση του. Μπορείτε να διαβάσετε περισσότερα για αυτό (αν και στα Αγγλικά) στο κείμενο του άδειου έργου DLL που δημιουργεί η Delphi (Αρχείο -> Νέο -> DLL). Οπότε καλύτερα χρησιμοποιήστε το PChar και μετά μετατρέψτε το σε συμβολοσειρά εάν χρειάζεται με τη λειτουργία StrPas.

Λοιπόν, τώρα ας αναλύσουμε απευθείας το ίδιο το DLL: Παράδειγμα 3. Πηγή έργου MYDLL.DPR
librarymydll;

Χρησιμοποιεί SysUtils, Classes.

(Ορίζουμε τη συνάρτηση ως stdcall)
συνάρτηση GetSimpleText(LangRus: Boolean): PChar; stdcall;
να αρχίσει
(Ανάλογα με το LangRus, επιστρέφουμε μια ρωσική (αληθής) ή αγγλική (ψευδή) φράση)
αν το LangRus τότε
Αποτέλεσμα:= PChar ("Hello World!")
αλλού
Αποτέλεσμα:= PChar("Γεια, κόσμο!");
τέλος;

(Η οδηγία εξαγωγών καθορίζει ποιες λειτουργίες θα εξάγονται από αυτό το DLL)
εξαγωγές GetSimpleText;

Να αρχίσει
τέλος.

Τοποθέτηση σε πόρους και φόρμες DLL

Σε ένα DLL, μπορείτε να τοποθετήσετε όχι μόνο λειτουργίες, αλλά και δρομείς, εικόνες, εικονίδια, μενού, γραμμές κειμένου. Δεν θα σταθούμε σε αυτό. Θα σημειώσω μόνο ότι για να φορτώσετε τον πόρο, πρέπει να φορτώσετε το DLL και, στη συνέχεια, έχοντας λάβει τον περιγραφέα του, φορτώστε τον ίδιο τον πόρο με την κατάλληλη συνάρτηση (LoadIcon, LoadCursor, κ.λπ.). Σε αυτήν την ενότητα, θα θίξουμε μόνο εν συντομία την τοποθέτηση των παραθύρων εφαρμογών (δηλ. φορμών στους Δελφούς) σε DLL.

Για να το κάνετε αυτό, πρέπει να δημιουργήσετε ένα νέο DLL και να προσθέσετε μια νέα φόρμα σε αυτό (Αρχείο -> Νέο -> DLL και μετά Αρχείο -> Νέα φόρμα). Επιπλέον, εάν η φόρμα είναι ένα παράθυρο διαλόγου (τροπική φόρμα (bsDialog)), τότε προσθέστε την ακόλουθη συνάρτηση στο DLL (για παράδειγμα, η φόρμα ονομάζεται Form1 και η κλάση της είναι TForm1): Παράδειγμα 4. Τοποθέτηση της φόρμας σε το DLL
συνάρτηση ShowMyDialog(Msg: PChar): Boolean; stdcall;

...
εξαγωγές ShowMyDialog;

Συνάρτηση ShowMyDialog(Msg: PChar): Boolean;
να αρχίσει
(Δημιουργήστε μια παρουσία του Form1 από τη μορφή TForm1)
Form1:= TForm1.Create(Application);
(Στην ετικέτα 1 εμφανίζουμε Μήνυμα)
Form1.Label1.Caption:= StrPas(Msg);
(Επιστροφή True μόνο αν πατηθεί OK (ModalResult = mrOk))
Αποτέλεσμα:= (Form1.ShowModal = mrOk);
(Απελευθέρωση μνήμης)
Form1.Free;
τέλος;

Εάν πρέπει να τοποθετήσετε μια μη-τροπική φόρμα στο DLL, τότε πρέπει να κάνετε δύο λειτουργίες - άνοιγμα και κλείσιμο της φόρμας. Σε αυτήν την περίπτωση, πρέπει να αναγκάσετε το DLL να θυμάται τη λαβή σε αυτήν τη φόρμα.

Δημιουργία πρόσθετων

Εδώ δεν θα εξετάσουμε λεπτομερώς τα πρόσθετα, γιατί. Τα παραδείγματα που έχουν ήδη δοθεί παραπάνω θα σας βοηθήσουν να κατανοήσετε εύκολα τη μερίδα του λέοντος στον προγραμματισμό DLL. Να υπενθυμίσω μόνο ότι το plug-in είναι μια προσθήκη στο πρόγραμμα που επεκτείνει τις δυνατότητές του. Ταυτόχρονα, το ίδιο το πρόγραμμα πρέπει απαραίτητα να προβλέπει την παρουσία τέτοιων προσθηκών και να τους επιτρέπει να εκπληρώσουν το σκοπό τους.

Δηλαδή, για παράδειγμα, για να δημιουργήσετε ένα πρόσθετο για ένα πρόγραμμα επεξεργασίας γραφικών που θα εκτελούσε μετατροπή εικόνας, πρέπει να παρέχετε τουλάχιστον δύο λειτουργίες στο πρόσθετο (και, κατά συνέπεια, να καλέσετε αυτές τις λειτουργίες στο πρόγραμμα) - μια συνάρτηση που θα επέστρεφε το όνομα της προσθήκης (ή/και τον τύπο της) για να προσθέσετε αυτήν την προσθήκη στο μενού (ή στη γραμμή εργαλείων), συν η κύρια λειτουργία είναι η αποστολή και λήψη μιας εικόνας. Εκείνοι. πρώτα, το πρόγραμμα αναζητά πρόσθετα, στη συνέχεια για κάθε ένα που βρέθηκε καλεί τη συνάρτηση αναγνώρισής του με ένα αυστηρά καθορισμένο όνομα (για παράδειγμα, GetPluginName) και προσθέτει το επιθυμητό στοιχείο στο μενού και, στη συνέχεια, εάν ο χρήστης έχει επιλέξει αυτό το στοιχείο, καλεί η δεύτερη συνάρτηση, η οποία μεταβιβάζει την εικόνα εισόδου (ή το όνομα αρχείου που περιέχει αυτήν την εικόνα) και αυτή η συνάρτηση, με τη σειρά της, επεξεργάζεται την εικόνα και την επιστρέφει σε νέα μορφή (ή όνομα αρχείου με νέα εικόνα). Αυτό είναι όλο το νόημα του πρόσθετου... :-)

Χρήση DLL στους Δελφούς
  • Η έννοια του DLL
  • Δημιουργία DLL στους Δελφούς (εξαγωγή)
  • Χρήση DLL στους Δελφούς (εισαγωγή)
  • DLL που χρησιμοποιούν αντικείμενα VCL για εργασία με δεδομένα
  • Εξαιρέσεις σε DLL
  • Η έννοια του DLL

Θυμηθείτε τη διαδικασία προγραμματισμού στο DOS. Η μετατροπή του πηγαίου κώδικα του προγράμματος σε κώδικα μηχανής περιελάμβανε δύο διαδικασίες - μεταγλώττιση και σύνδεση. Κατά τη διαδικασία σύνδεσης, ο σύνδεσμος, ο οποίος συνέδεε μεμονωμένες ενότητες προγράμματος, τοποθέτησε στον κώδικα του προγράμματος όχι μόνο δηλώσεις λειτουργιών και διαδικασιών, αλλά και τον πλήρη κωδικό τους. Ετοίμασες ένα πρόγραμμα με αυτόν τον τρόπο, ένα άλλο, ένα τρίτο... Και παντού ο κώδικας των ίδιων συναρτήσεων ήταν εντελώς τοποθετημένος στο πρόγραμμα.

Πρόγραμμα1 Πρόγραμμα2: : MyFunc(:) MyFunc(:) : : κωδικός συνάρτησης Κωδικός συνάρτησης MyFunc Κωδικός MyFunc άλλων συναρτήσεων Κωδικός άλλων συναρτήσεων

Σε ένα περιβάλλον πολλαπλών εργασιών, μια τέτοια προσέγγιση θα ήταν τουλάχιστον απερίσκεπτη, καθώς είναι προφανές ότι ένας τεράστιος αριθμός από τις ίδιες λειτουργίες είναι υπεύθυνες για τη σχεδίαση στοιχείων διεπαφής χρήστη, την πρόσβαση σε πόρους του συστήματος κ.λπ. θα ήταν εντελώς διπλό σε όλες τις εφαρμογές, γεγονός που θα οδηγούσε στην ταχεία εξάντληση του πιο ακριβού πόρου - της μνήμης RAM. Ως λύση σε αυτό το πρόβλημα, ακόμη και σε πλατφόρμες τύπου UNIX, προτάθηκε η έννοια της δυναμικής σύνδεσης (βλ. Εικ. 2).

Ποια είναι όμως η διαφορά μεταξύ της Dynamic Link Library (DLL) και των κανονικών εφαρμογών; Για να γίνει κατανοητό αυτό, είναι απαραίτητο να διευκρινιστούν οι έννοιες μιας εργασίας (εργασίας), μιας παρουσίας (αντίγραφου) μιας εφαρμογής (στιγμής) και μιας ενότητας (ενότητα).

Όταν εκτελούνται πολλαπλές παρουσίες μιας μεμονωμένης εφαρμογής, τα Windows φορτώνουν στη μνήμη RAM μόνο ένα αντίγραφο του κώδικα και των πόρων - τη λειτουργική μονάδα της εφαρμογής, δημιουργώντας πολλά ξεχωριστά τμήματα δεδομένων, μια στοίβα και μια ουρά μηνυμάτων (βλ. Εικ. 3), κάθε σύνολο των οποίων είναι μια εργασία, στην κατανόηση των Windows. Το αντίγραφο της εφαρμογής είναι το πλαίσιο στο οποίο εκτελείται η λειτουργική μονάδα της εφαρμογής.

DLL - μια βιβλιοθήκη είναι επίσης μια ενότητα. Βρίσκεται στη μνήμη σε ένα μόνο αντίγραφο και περιέχει ένα τμήμα κώδικα και πόρους, καθώς και ένα τμήμα δεδομένων (βλ. Εικόνα 4).

Ένα DLL είναι μια βιβλιοθήκη, σε αντίθεση με μια εφαρμογή, δεν έχει ούτε στοίβα ούτε ουρά μηνυμάτων. Οι συναρτήσεις που τοποθετούνται σε ένα DLL εκτελούνται στο πλαίσιο της εφαρμογής κλήσης, χρησιμοποιώντας τη στοίβα της. Αλλά αυτές οι ίδιες λειτουργίες χρησιμοποιούν το τμήμα δεδομένων της βιβλιοθήκης και όχι το αντίγραφο της εφαρμογής.

Λόγω αυτής της οργάνωσης του DLL, επιτυγχάνεται εξοικονόμηση μνήμης λόγω του γεγονότος ότι όλες οι εφαρμογές που εκτελούνται χρησιμοποιούν μία μονάδα DLL, χωρίς να συμπεριλαμβάνονται ορισμένες τυπικές λειτουργίες στις μονάδες τους.

Συχνά, με τη μορφή ενός DLL, δημιουργούνται ξεχωριστά σύνολα συναρτήσεων, που συνδυάζονται σύμφωνα με το ένα ή το άλλο λογικό χαρακτηριστικό, παρόμοια με τον τρόπο με τον οποίο οι ενότητες σχεδιάζονται εννοιολογικά (με την έννοια μιας μονάδας) στο Pascal. Η διαφορά είναι ότι οι συναρτήσεις από τις μονάδες Pascal συνδέονται στατικά - στο στάδιο της σύνδεσης, και οι συναρτήσεις από τα DLL συνδέονται δυναμικά, δηλαδή κατά το χρόνο εκτέλεσης.

Δημιουργία DLL στους Δελφούς (εξαγωγή)

Για τον προγραμματισμό DLL, το Delphi παρέχει μια σειρά από λέξεις-κλειδιά και κανόνες σύνταξης. Το κύριο πράγμα - το DLL στους Δελφούς είναι το ίδιο έργο με ένα πρόγραμμα.

Εξετάστε ένα πρότυπο DLL:


Το όνομα αρχείου έργου για ένα τέτοιο πρότυπο πρέπει να είναι MYDLL.DPR.

Δυστυχώς, μόνο το έργο προγράμματος δημιουργείται αυτόματα στο Delphi IDE, επομένως πρέπει να προετοιμάσετε το έργο DLL με μη αυτόματο τρόπο. Το Delphi 2.0 έχει αφαιρέσει αυτήν την ταλαιπωρία.

Όπως ένα πρόγραμμα, ένα DLL έχει μια ενότητα χρήσεων. Το τμήμα προετοιμασίας είναι προαιρετικό. Η ενότητα εξαγωγών παραθέτει τις λειτουργίες στις οποίες θα πρέπει να έχετε πρόσβαση από εξωτερικές εφαρμογές.

Η εξαγωγή συναρτήσεων (και διαδικασιών) μπορεί να γίνει με διάφορους τρόπους:

  • κατά αριθμό (ευρετήριο)
  • με το όνομα

Ανάλογα με αυτό, χρησιμοποιείται διαφορετική σύνταξη:


Δεδομένου ότι τα Windows έχουν την έννοια των "συναρτήσεων κατοίκου" ενός DLL, δηλαδή εκείνων των συναρτήσεων που βρίσκονται στη μνήμη καθ' όλη τη διάρκεια ζωής ενός DLL στη μνήμη, οι Delphi διαθέτουν εργαλεία για την οργάνωση και τέτοιου είδους εξαγωγή:


τότε η ευρετηρίαση των εξαγόμενων συναρτήσεων θα γίνει αυτόματα από τους Delphi και μια τέτοια εξαγωγή θα θεωρείται εξαγωγή με το όνομα που ταιριάζει με το όνομα της συνάρτησης. Στη συνέχεια, η δήλωση της εισαγόμενης συνάρτησης στην εφαρμογή πρέπει να ταιριάζει με το όνομα της δήλωσης συνάρτησης στο DLL. Όσο για τις οδηγίες που έχουν ήδη επιβληθεί σε εισαγόμενες λειτουργίες, θα μιλήσουμε για αυτό παρακάτω.

Χρήση DLL στους Δελφούς (εισαγωγή)

Να οργανώσει τις εισαγωγές, δηλ. Πρόσβαση σε λειτουργίες που εξάγονται από ένα DLL, καθώς και εξαγωγή τους, η Delphi παρέχει τυπικές εγκαταστάσεις.

Για τα παραδείγματα που εμφανίζονται παραπάνω, το πρόγραμμά σας θα πρέπει να δηλώσει τις συναρτήσεις που εισάγονται από το DLL ως εξής:


Αυτή η μέθοδος ονομάζεται στατική εισαγωγή.

Όπως ίσως έχετε παρατηρήσει, η επέκταση του αρχείου που περιέχει το DLL δεν καθορίζεται - από προεπιλογή, θεωρούνται αρχεία *.DLL και *.EXE. Πώς θα γίνει εάν το αρχείο έχει διαφορετική επέκταση (για παράδειγμα, όπως το COMPLIB.DCL στους Δελφούς), ή εάν απαιτείται δυναμικός ορισμός του DLL και των εισαγόμενων συναρτήσεων (για παράδειγμα, το πρόγραμμά σας λειτουργεί με διαφορετικές μορφές γραφικών και για καθεμία από υπάρχει ξεχωριστό DLL.);

Για να λύσετε αυτό το είδος προβλήματος, μπορείτε να αποκτήσετε απευθείας πρόσβαση στο API των Windows χρησιμοποιώντας τη λεγόμενη δυναμική εισαγωγή:


χρήσεις WinTypes, WinProcs, ... ; τύπος TMyProc = διαδικασία ; varΛαβή: THandle; MyImportProc: TMyProc; να αρχίσει Handle:= LoadLibrary("MYDLL"); ανΛαβή >= 32 έπειτα (αν να αρχίσει@MyImportProc:= GetProcAddress(Handle, "MYEXPORTPROC"); αν MyImportProc μηδέν έπειτα ... (με χρήση διαδικασίας εισαγωγής) τέλος; FreeLibrary(Handle); τέλος;

Συντακτικά διαγράμματα δηλώσεων εξαγωγής/εισαγωγής, αντικατάσταση σημείου εξόδου DLL και άλλα παραδείγματα βρίσκονται στο OnLine Help Delphi, στον Οδηγό γλώσσας Object Pascal που περιλαμβάνεται στο Borland RAD Pack για τους Delphi και, για παράδειγμα, στο βιβλίο "Teach Yourself Δελφοί σε 21 μέρες».

Εκτός από τον κώδικα που δημιουργείται από τον μεταγλωττιστή (τώρα είναι πιο βελτιστοποιημένος), τότε όλοι οι κανόνες σύνταξης παραμένουν ίδιοι όπως στο Borland Pascal 7.0

DLL που χρησιμοποιούν αντικείμενα VCL για εργασία με δεδομένα

Όταν δημιουργείτε τη δική σας δυναμική βιβλιοθήκη, μπορείτε να χρησιμοποιήσετε κλήσεις λειτουργιών από άλλα DLL. Ένα παράδειγμα τέτοιου DLL είναι η διανομή Delphi (X:\DELPHI\DEMOS\BD\BDEDLL). Αυτό το DLL περιέχει μια φόρμα που εμφανίζει δεδομένα από έναν πίνακα και χρησιμοποιεί αντικείμενα VCL (TTable, TDBGrid, TSession) για πρόσβαση σε αυτό, τα οποία, με τη σειρά τους, καλούν συναρτήσεις BDE. Όπως προκύπτει από τα σχόλια σε αυτό το παράδειγμα, υπάρχει ένας περιορισμός για ένα τέτοιο DLL: δεν μπορεί να χρησιμοποιηθεί από πολλές εργασίες ταυτόχρονα. Αυτό συμβαίνει επειδή το αντικείμενο Session, το οποίο δημιουργείται αυτόματα όταν συνδέεται η λειτουργική μονάδα DB, προετοιμάζεται για τη λειτουργική μονάδα και όχι για την εργασία. Εάν προσπαθήσετε να φορτώσετε αυτό το DLL δεύτερη φορά από άλλη εφαρμογή, θα λάβετε ένα σφάλμα. Για να αποτρέψετε την ταυτόχρονη φόρτωση ενός DLL πολλαπλών εργασιών, πρέπει να γίνουν ορισμένα βήματα. Στο παράδειγμα, αυτή είναι η διαδικασία για τον έλεγχο εάν το DLL χρησιμοποιείται αυτήν τη στιγμή από άλλη εργασία.

Εξαιρέσεις σε DLL

Η εισαγωγή μιας εξαίρεσης σε ένα DLL που δημιουργήθηκε από τους Delphi θα προκαλέσει τον τερματισμό ολόκληρης της εφαρμογής, εάν η εξαίρεση δεν έχει διεκπεραιωθεί στο DLL. Επομένως, είναι επιθυμητό να προβλεφθούν όλα τα πιθανά προβλήματα κατά τη στιγμή της ανάπτυξης του DLL. Μπορούμε να σας προτείνουμε να επιστρέψετε το αποτέλεσμα της εισαγόμενης συνάρτησης ως συμβολοσειρά ή αριθμό και, εάν χρειάζεται, να επαναφέρετε την εξαίρεση στο πρόγραμμα.


λειτουργία MyFunc: σειρά; να αρχίσει προσπαθήστε (πραγματικός κωδικός λειτουργίας) εκτός επίΑποτέλεσμα: Εξαίρεση κάνωΑποτέλεσμα:=Μορφή(DllErrorViewingTable, ) αλλούΑποτέλεσμα:= Μορφή(DllErrorViewingTable, ["Άγνωστο σφάλμα"]); τέλος; τέλος;

Κωδικός στο πρόγραμμα:


StrResult:= MyFunc; αν StrΑποτέλεσμα "" έπειτα υψώνω Exception.Create(StrResult);

Αρθρο Χρήση DLL στους ΔελφούςΗ ενότητα DLL Filesystem and PlugIns μπορεί να είναι χρήσιμη για προγραμματιστές Delphi και FreePascal.

Φέρνω στην προσοχή σας το επόμενο τεύχος του ενημερωτικού δελτίου, στο οποίο συνεχίζω να συζητώ
θέματα ανάπτυξης και χρήσης DLL στο Borland Delphi. Για νέους συνδρομητές σας ενημερώνω,
ότι μπορούν να δουν το πρώτο μέρος του άρθρου στο αρχείο της λίστας αλληλογραφίας, τεύχος 13.
Ζητώ συγγνώμη από όσους μου έγραψαν, αλλά δεν έλαβαν απάντηση. Θα προσπαθήσω να το διορθώσω στο εγγύς μέλλον.
Ας συνεχίσουμε λοιπόν.

Πριν ξεκινήσετε να χρησιμοποιείτε οποιαδήποτε διαδικασία ή συνάρτηση που βρίσκεται στη δυναμική βιβλιοθήκη,
πρέπει να φορτώσετε το DLL στη μνήμη RAM. Η φόρτωση της βιβλιοθήκης μπορεί να γίνει
ένας από τους δύο τρόπους: στατική φόρτωση και δυναμική φόρτωση.
Και οι δύο μέθοδοι έχουν και πλεονεκτήματα και μειονεκτήματα.
Στατική φόρτωση σημαίνει ότι η δυναμική βιβλιοθήκη φορτώνεται αυτόματα
όταν εκκινηθεί η εφαρμογή που το χρησιμοποιεί. Για να χρησιμοποιήσετε αυτήν τη μέθοδο λήψης,
πρέπει να χρησιμοποιήσετε την εξωτερική λέξη-κλειδί κατά την περιγραφή της εξαγωγής από
λειτουργία ή διαδικασία δυναμικής βιβλιοθήκης. Το DLL φορτώνεται αυτόματα όταν ξεκινά το πρόγραμμα,
και θα μπορείτε να χρησιμοποιήσετε όλες τις υπορουτίνες που εξάγονται από αυτό με τον ίδιο τρόπο
σαν να περιγράφονταν μέσα σε ενότητες εφαρμογής.
Αυτός είναι ο ευκολότερος τρόπος χρήσης κώδικα που τοποθετείται σε ένα DLL.
Το μειονέκτημα της μεθόδου είναι ότι αν το αρχείο βιβλιοθήκης στο οποίο
υπάρχει ένας σύνδεσμος στην εφαρμογή, απουσιάζει, το πρόγραμμα θα αρνηθεί να φορτώσει.
Το νόημα της δυναμικής μεθόδου είναι ότι δεν φορτώνετε τη βιβλιοθήκη στην αρχή της εφαρμογής,
και τη στιγμή που το έχεις πραγματικά ανάγκη. Κρίνετε μόνοι σας, γιατί αν η λειτουργία που περιγράφεται
σε μια δυναμική βιβλιοθήκη, χρησιμοποιείται μόνο στο 10% των εκκινήσεων προγραμμάτων, τότε απολύτως όχι
δεν έχει νόημα να χρησιμοποιήσετε μια μέθοδο στατικού φορτίου. Ξεφόρτωση της βιβλιοθήκης από τη μνήμη σε αυτήν την περίπτωση
είναι επίσης υπό τον έλεγχό σας. Ένα άλλο πλεονέκτημα αυτής της μεθόδου
Η φόρτωση DLL είναι μια μείωση (για προφανείς λόγους) στον χρόνο έναρξης της εφαρμογής σας.
Και ποια είναι τα μειονεκτήματα αυτής της μεθόδου; Το κυριότερο, μου φαίνεται, είναι ότι η χρήση
Αυτή η μέθοδος είναι πιο ενοχλητική από τη στατική φόρτωση που συζητήθηκε παραπάνω.
Πρώτα πρέπει να χρησιμοποιήσετε τη λειτουργία LoadLibrary Windows API.
Για να αποκτήσετε έναν δείκτη σε μια διαδικασία ή συνάρτηση που εξάγεται,
χρησιμοποιήστε τη συνάρτηση GetProcAddress. Αφού ολοκληρώσετε τη χρήση του DLL
πρέπει να γίνει λήψη χρησιμοποιώντας τη FreeLibrary.
Κλήση διαδικασιών και συναρτήσεων που έχουν φορτωθεί από ένα DLL.
Ο τρόπος που καλούνται οι διαδικασίες και οι συναρτήσεις εξαρτάται από το πώς φορτώσατε τη δυναμική βιβλιοθήκη,
στο οποίο βρίσκονται αυτές οι υπορουτίνες.
Η κλήση συναρτήσεων και διαδικασιών από στατικά φορτωμένα DLL είναι αρκετά απλή. Αρχικά στην εφαρμογή
πρέπει να περιέχει περιγραφή της εξαγόμενης λειτουργίας (διαδικασίας). Μετά από αυτό μπορείτε να τα χρησιμοποιήσετε
με τον ίδιο τρόπο σαν να περιγράφονταν σε μια από τις ενότητες της αίτησής σας.
Για να εισαγάγετε μια συνάρτηση ή μια διαδικασία που περιέχεται σε ένα DLL, πρέπει να χρησιμοποιήσετε
τον εξωτερικό τροποποιητή στη δήλωσή τους. Για παράδειγμα, για τη διαδικασία HelloWorld που συζητήσαμε παραπάνω
Η ακόλουθη γραμμή πρέπει να τοποθετηθεί στην εφαρμογή κλήσης:
διαδικασία SayHello(AForm: TForm); εξωτερικό myfirstdll.dll";
Η εξωτερική λέξη-κλειδί λέει στον μεταγλωττιστή ότι μπορεί να βρεθεί η διαδικασία
δυναμική βιβλιοθήκη (στην περίπτωσή μας, myfirstdll.dll).
Στη συνέχεια, η κλήση σε αυτήν τη διαδικασία μοιάζει με αυτό:
...
HelloWorld(self);
...
Κατά την εισαγωγή συναρτήσεων και διαδικασιών, να είστε ιδιαίτερα προσεκτικοί όταν γράφετε τα ονόματα και τις διεπαφές τους!
Το γεγονός είναι ότι κατά τη διαδικασία κατάρτισης της αίτησης, δεν πραγματοποιείται έλεγχος για την ορθότητα των ονομάτων αντικειμένων,
που εξάγονται από το DLL δεν θα εφαρμοστεί και εάν περιγράψατε λανθασμένα κάποια λειτουργία,
τότε η εξαίρεση θα γίνει μόνο κατά το χρόνο εκτέλεσης της εφαρμογής.
Η εισαγωγή από ένα DLL μπορεί να γίνει με όνομα διαδικασίας (συνάρτησης), τακτικό αριθμό ή
με διαφορετικό όνομα.
Στην πρώτη περίπτωση, δηλώνετε απλώς το όνομα της διαδικασίας και τη βιβλιοθήκη από την οποία την εισάγετε.
(το συζητήσαμε λίγο παραπάνω). Η εισαγωγή με σειριακό αριθμό απαιτεί να καθορίσετε αυτόν ακριβώς τον αριθμό:
διαδικασία HelloWorld(AForm: TForm); εξωτερικό ευρετήριο myfirstdll.dll 15;
Σε αυτήν την περίπτωση, το όνομα που δίνετε στη διαδικασία κατά την εισαγωγή δεν χρειάζεται να είναι το ίδιο με αυτό
που είχε καθοριστεί για αυτό στο ίδιο το DLL. Εκείνοι. το παραπάνω λήμμα σημαίνει
ότι εισάγετε από τη δυναμική βιβλιοθήκη myfirstdll.dll τη διαδικασία που εξήχθη σε αυτήν
δέκατο πέμπτο, και στην αίτησή σας, αυτή η διαδικασία ονομάζεται SayHello.
Εάν για κάποιο λόγο δεν χρησιμοποιείτε τη μέθοδο εισαγωγής που περιγράφεται παραπάνω,
αλλά εξακολουθείτε να θέλετε να αλλάξετε το όνομα της εισαγόμενης συνάρτησης (διαδικασία), μπορείτε να χρησιμοποιήσετε την τρίτη μέθοδο:
διαδικασία CoolProcedure; εξωτερικό όνομα myfirstdll.dll "DoSomethingReallyCool".
Εδώ, η εισαγόμενη διαδικασία CoolProcedure ονομάζεται DoSomethingReallyCool.
Διαδικασίες κλήσης και συναρτήσεις που εισάγονται από δυναμικά φορτωμένες βιβλιοθήκες
κάπως πιο περίπλοκη από τη μέθοδο που συζητήθηκε παραπάνω. Σε αυτή την περίπτωση, πρέπει να δηλώσετε
έναν δείκτη για τη λειτουργία ή τη διαδικασία που πρόκειται να χρησιμοποιήσετε.
Θυμάστε τη διαδικασία του HelloWorld; Ας δούμε τι πρέπει να γίνει για να γίνει
για να το καλέσετε για εκτέλεση σε περίπτωση δυναμικής φόρτωσης του DLL. Πρώτα εσύ
είναι απαραίτητο να δηλώσετε έναν τύπο που θα περιγράφει αυτή τη διαδικασία:
τύπος
THelloWorld = διαδικασία (AForm: TForm);
Τώρα πρέπει να φορτώσετε τη δυναμική βιβλιοθήκη, χρησιμοποιήστε το GetProcAddress για λήψη
έναν δείκτη σε μια διαδικασία, καλέστε αυτήν τη διαδικασία για εκτέλεση και, τέλος, ξεφορτώστε το DLL από τη μνήμη.
Ακολουθεί ένας κώδικας που δείχνει πώς μπορεί να γίνει αυτό:

DLLInstance: THandle ;

HelloWorld:ThelloWorld;

να αρχίσει

(φόρτωση DLL)

(λάβετε δείκτη)

(καλέστε τη διαδικασία να εκτελεστεί)

HelloWorld(Self ) ;

(ξεφόρτωση DLL από RAM)

FreeLibrary(DLLInstance) ;

τέλος ;

Όπως αναφέρθηκε παραπάνω, ένα από τα μειονεκτήματα της στατικής φόρτωσης ενός DLL είναι η αδυναμία
συνεχίστε την εφαρμογή ελλείψει μιας ή περισσότερων βιβλιοθηκών. Στην περίπτωση της δυναμικής
φόρτωση, έχετε την ευκαιρία να χειριστείτε μέσω προγραμματισμού τέτοιες καταστάσεις και να αποτρέψετε το πρόγραμμα
έπεσε έξω από μόνη της. Σύμφωνα με τις τιμές που επιστρέφονται από τις λειτουργίες LoadLibrary και GetProcAddress, μπορείτε να
προσδιορίστε εάν η φόρτωση της βιβλιοθήκης ήταν επιτυχής και εάν βρέθηκε σε αυτήν η διαδικασία που απαιτείται από την εφαρμογή.
Ο παρακάτω κώδικας το δείχνει αυτό.

διαδικασία TForm1.DynamicLoadBtnClick (Αποστολέας: TObject ) ;

τύπος

THelloWorld = διαδικασία (AForm: TForm) ;

DLLInstance: THandle ;

HelloWorld:ThelloWorld;

να αρχίσει

DLLInstance:= LoadLibrary("myfirstdll.dll" );

εάν DLLInstance = 0, τότε ξεκινήστε

MessageDlg( "Δεν είναι δυνατή η φόρτωση DLL", mtError, [ mbOK] , 0 );

έξοδος;

τέλος ;

@HelloWorld:= GetProcAddress(DLLInstance, "HelloWorld");

αν @HelloWorld μηδέν τότε

HelloWorld (Εαυτός)

αλλού

MessageDlg( "Η διαδικασία που ζητήθηκε δεν βρέθηκε!", mtError, [ mbOK] , 0 );

FreeLibrary(DLLInstance) ;

τέλος ;

Στο DLL, μπορείτε να αποθηκεύσετε όχι μόνο κώδικα, αλλά και φόρμες.
Επιπλέον, η δημιουργία και η τοποθέτηση φορμών σε μια δυναμική βιβλιοθήκη δεν διαφέρει πολύ από την εργασία
με έντυπα σε κανονικό έργο. Αρχικά, θα εξετάσουμε πώς μπορείτε να γράψετε μια βιβλιοθήκη,
που περιέχει φόρμες και, στη συνέχεια, θα μιλήσουμε για τη χρήση της τεχνολογίας MDI σε ένα DLL.
Θα δείξω την ανάπτυξη ενός DLL που περιέχει μια φόρμα με ένα παράδειγμα.
Λοιπόν, πρώτα, ας δημιουργήσουμε ένα νέο έργο δυναμικής βιβλιοθήκης.
Για να το κάνετε αυτό, επιλέξτε το στοιχείο μενού Αρχείο|Νέο και, στη συνέχεια, κάντε διπλό κλικ στο εικονίδιο DLL.
Μετά από αυτό, θα δείτε κάτι σαν τον ακόλουθο κώδικα:

Αποθηκεύστε το έργο που προκύπτει. Ας το ονομάσουμε DllForms.dpr.
Τώρα πρέπει να δημιουργήσουμε μια νέα φόρμα. Αυτό μπορεί να γίνει με διάφορους τρόπους.
Για παράδειγμα, επιλέγοντας το στοιχείο μενού Αρχείο|Νέα φόρμα. Προσθέστε μερικά στοιχεία στη φόρμα.
Ας ονομάσουμε τη φόρμα DllForm και ας αποθηκεύσουμε τη μονάδα που προκύπτει ως DllFormUnit.pas .
Ας επιστρέψουμε στην κύρια ενότητα του έργου και ας τοποθετήσουμε τη συνάρτηση ShowForm σε αυτήν, η εργασία της οποίας θα περιλαμβάνει
τη δημιουργία μιας φόρμας και την εμφάνισή της στην οθόνη. Χρησιμοποιήστε τον παρακάτω κώδικα για αυτό.

Μορφή: TDLLForm;

να αρχίσει

Αποτέλεσμα:= Form.ShowModal ;

Φόρμα.Δωρεάν ;

τέλος ;

Εφιστώ την προσοχή σας στο γεγονός ότι για να γίνει η μεταγλώττιση του έργου χωρίς σφάλματα, είναι απαραίτητο να προστεθεί η ενότητα Φόρμες στην ενότητα χρήσεις.
Εξάγουμε τη συνάρτησή μας χρησιμοποιώντας τη λέξη-κλειδί εξαγωγές:
εξαγωγές
ShowForm;
Μεταγλωττίζουμε το έργο και παίρνουμε το αρχείο dllforms.dll. Αυτά τα απλά βήματα είναι το παν
τι πρέπει να κάνετε για τη συλλογή Σημειώστε ότι η συνάρτηση ShowForm δηλώνεται χρησιμοποιώντας τη λέξη-κλειδί stdcall.
Σηματοδοτεί τον μεταγλωττιστή να χρησιμοποιήσει τη σύμβαση κατά την εξαγωγή μιας συνάρτησης
με τυπική σύμβαση κλήσης. Η εξαγωγή μιας συνάρτησης με αυτόν τον τρόπο δημιουργεί
τη δυνατότητα χρήσης του αναπτυγμένου DLL όχι μόνο σε εφαρμογές που δημιουργούνται στους Δελφούς.
Οι συμβάσεις κλήσης ορίζουν πώς μεταβιβάζονται ορίσματα όταν καλείται μια συνάρτηση.
Υπάρχουν πέντε βασικές συμβάσεις: stdcall, cdecl, pascal, register και safecall.
Μπορείτε να μάθετε περισσότερα σχετικά με αυτό ανατρέχοντας στην ενότητα "Συμβάσεις κλήσης" του αρχείου βοήθειας των Delphi.
Σημειώστε επίσης ότι η τιμή που επιστρέφεται από τη συνάρτηση ShowForm,
αντιστοιχεί στην τιμή ShowModal. Με αυτόν τον τρόπο μπορείτε να περάσετε κάποιες πληροφορίες
σχετικά με την κατάσταση της φόρμας στην αίτηση κλήσης.
Ακολουθούν δύο καταχωρίσεις, η πρώτη από τις οποίες περιέχει τον πλήρη κωδικό αρχείου
Έργο DLL (η ενότητα με τη φόρμα δεν εμφανίζεται εδώ) και η δεύτερη είναι η ενότητα της εφαρμογής που καλεί,
που χρησιμοποιεί τη βιβλιοθήκη που μόλις αναπτύξαμε.

βιβλιοθήκη DllForms?

χρήσεις

DllFormUnit στο "DllFormUnit.pas" (DllForm) ;

($R*.RES)

συνάρτηση ShowForm: Integer ; stdcall ;

Μορφή: TDLLForm;

να αρχίσει

Form:= TDLLForm.Create(Application) ;

Αποτέλεσμα:= Form.ShowModal ;

Φόρμα.Δωρεάν ;

τέλος ;

να αρχίσει

τέλος.


μονάδα TestAppUnit;

διεπαφή

χρήσεις

Windows, Messages, SysUtils, Classes, Graphics,

Στοιχεία ελέγχου, φόρμες, διάλογοι, StdCtrls;

τύπος

TForm1 = κλάση (TForm)

Κουμπί 1: TButton;

διαδικασία Button1Click(Αποστολέας: TObject ) ;

ιδιωτικός

(Ιδιωτικές δηλώσεις)

δημόσιο

(Δημόσιες δηλώσεις)

τέλος ;

Form1: TForm1;

συνάρτηση ShowForm: Integer ; stdcall ;

Εξωτερικό "dllforms.dll" ;

εκτέλεση

($R *.DFM)

διαδικασία TForm1.Button1Click (Αποστολέας: TObject ) ;

να αρχίσει

τέλος ;

τέλος.

Λάβετε υπόψη ότι η λέξη-κλειδί stdcall χρησιμοποιήθηκε επίσης κατά την εξαγωγή της συνάρτησης.
Θα πρέπει να δώσετε ιδιαίτερη προσοχή στην εργασία με θυγατρικές φόρμες στο DLL. Αν, για παράδειγμα,
στην εφαρμογή κλήσης, η κύρια φόρμα έχει την ιδιότητα FormStyle σε MDIForm,
στη συνέχεια, όταν προσπαθείτε να καλέσετε από τη φόρμα MDIChild DLL, θα εμφανιστεί ένα μήνυμα σφάλματος στην οθόνη,
που θα πει ότι δεν υπάρχει ενεργή φόρμα MDI.
Τη στιγμή που προσπαθείτε να εμφανίσετε το παράθυρο του παιδιού σας, το VCL ελέγχει για την ορθότητα
την ιδιότητα FormStyle της κύριας φόρμας της εφαρμογής. Ωστόσο, στην περίπτωσή μας, όλα δείχνουν να είναι σωστά.
Ποια είναι λοιπόν η συμφωνία; Το πρόβλημα είναι ότι κατά τη διεξαγωγή ενός τέτοιου ελέγχου, λαμβάνεται υπόψη το αντικείμενο της εφαρμογής,
δεν ανήκει στην καλούσα εφαρμογή, αλλά στην ίδια τη δυναμική βιβλιοθήκη.
Λοιπόν, φυσικά, καθώς δεν υπάρχει κύρια φόρμα στο DLL, ο έλεγχος δίνει ένα σφάλμα.
Για να αποφευχθεί αυτή η κατάσταση, είναι απαραίτητο να αντιστοιχίσετε στο αντικείμενο Εφαρμογή της δυναμικής βιβλιοθήκης
το αντικείμενο Εφαρμογής της καλούσας εφαρμογής. Φυσικά, αυτό θα λειτουργήσει μόνο εάν
όταν το πρόγραμμα κλήσης είναι εφαρμογή VCL. Επιπλέον, πριν ξεφορτώσετε τη βιβλιοθήκη από τη μνήμη
είναι απαραίτητο να επιστρέψετε την τιμή του αντικειμένου εφαρμογής της βιβλιοθήκης στην αρχική του κατάσταση.
Αυτό θα επιτρέψει στον διαχειριστή μνήμης να καθαρίσει τη μνήμη RAM που καταλαμβάνει η βιβλιοθήκη.
Επομένως, πρέπει να αποθηκεύσετε έναν δείκτη στο εγγενές αντικείμενο Εφαρμογής της βιβλιοθήκης.
σε μια καθολική μεταβλητή που μπορεί να χρησιμοποιηθεί κατά την επαναφορά της τιμής της.
Ας πάμε λοιπόν λίγο πίσω και ας απαριθμήσουμε τα βήματα που χρειαζόμαστε για να δουλέψουμε με το τοποθετημένο
σε μορφές DLL MDIChild.
Στη δυναμική βιβλιοθήκη, δημιουργούμε μια καθολική μεταβλητή τύπου TApplication.
Αποθηκεύουμε έναν δείκτη στο αντικείμενο DLL της εφαρμογής σε μια καθολική μεταβλητή.
Αντιστοιχίζουμε έναν δείκτη στο Application στο αντικείμενο Application της δυναμικής βιβλιοθήκης
αίτηση κλήσης.
Δημιουργούμε μια φόρμα MDIChild και δουλεύουμε με αυτήν.
Επιστρέφουμε την τιμή του αντικειμένου Εφαρμογή της δυναμικής βιβλιοθήκης στην αρχική του κατάσταση
και ξεφορτώστε το DLL από τη μνήμη.
Το πρώτο βήμα είναι απλό. Απλώς τοποθετήστε τον ακόλουθο κώδικα στην κορυφή της μονάδας DLL:
var
DllApp: TApplication;
Στη συνέχεια δημιουργούμε μια διαδικασία που θα αλλάξει την τιμή του αντικειμένου Εφαρμογή και θα δημιουργήσει μια θυγατρική φόρμα.
Η διαδικασία μπορεί να μοιάζει κάπως έτσι:

διαδικασία ShowMDIChild(MainApp: TApplication) ;

Παιδί: TMDIChild;

να αρχίσει

εάν δεν έχει εκχωρηθεί (DllApp), τότε ξεκινήστε

DllApp:= Εφαρμογή;

Εφαρμογή:= MainApp;

τέλος ;

Child:= TMDIChild.Create (Application.MainForm) ;

Παιδί.Εμφάνιση ;

τέλος ;

Το μόνο που χρειάζεται να κάνουμε τώρα είναι να παρέχουμε την επιστροφή της τιμής του αντικειμένου Εφαρμογή.
στην αρχική κατάσταση. Αυτό το κάνουμε χρησιμοποιώντας τη διαδικασία MyDllProc:

διαδικασία MyDLLProc(Λόγος: Ακέραιος ) ;

να αρχίσει

αν Λόγος = DLL_PROCESS_DETACH τότε

(Το DLL εκφορτώνεται. Επαναφορά της τιμής του δείκτη εφαρμογής)

εάν έχει εκχωρηθεί (DllApp) τότε

Εφαρμογή:= DllApp;

τέλος ;

αντί για συμπέρασμα.
Η χρήση βιβλιοθηκών δυναμικών συνδέσμων δεν είναι τόσο δύσκολη όσο μπορεί να φαίνεται με την πρώτη ματιά.

Η χρήση βιβλιοθηκών δυναμικών συνδέσμων δεν είναι τόσο δύσκολη όσο μπορεί να φαίνεται με την πρώτη ματιά.
Τα DLL παρέχουν τις ευρύτερες δυνατότητες βελτιστοποίησης της απόδοσης των εφαρμογών,
καθώς και το έργο των ίδιων των προγραμματιστών. Χρησιμοποιήστε το DLL και ίσως η ζωή σας να είναι πιο εύκολη!
http://subscribe.ru/
ΗΛΕΚΤΡΟΝΙΚΗ ΔΙΕΥΘΥΝΣΗ: [email προστατευμένο]Αναζήτηση
στο APORT στο Subscribe.Ru

Περισσότερες από μία φορές χρειάστηκε να λάβουμε επιστολές με το αίτημα να ενημερώσουμε για τη δημιουργία και τη χρήση του DLL στους Δελφούς. Σε αυτό το άρθρο, θα ασχοληθούμε με τα πάντα και θα δημιουργήσουμε τη δική μας βιβλιοθήκη. Οι δυναμικά συνδεδεμένες βιβλιοθήκες (Dinamic Link Library) επιτρέπουν σε διαφορετικές εφαρμογές να χρησιμοποιούν ένα κοινό σύνολο πόρων στην εργασία τους. Το σημαντικό είναι ότι οι διαδικασίες και οι συναρτήσεις που τοποθετούνται στο DLL εκτελούνται μέσα στη διεργασία που τις χρησιμοποιεί. Ένα DLL παρέχει σε όλες τις εφαρμογές ένα μόνο αντίγραφο ενός πόρου που είναι κοινόχρηστο από όλες τις εφαρμογές που το ζητούν, σε αντίθεση με τις ρουτίνες που εκτελούν ξεχωριστό αντίγραφο για κάθε εφαρμογή που τις καλεί. Επίσης, στη διαφορά μεταξύ DLL και υπορουτίνων, μπορεί κανείς να συμπεριλάβει το γεγονός ότι τα DLL μπορούν να εξάγουν μόνο διαδικασίες και συναρτήσεις, αλλά όχι τύπους, σταθερές κ.λπ.

Θα ήθελα να δώσω ένα απόσπασμα από τα "Μαθήματα στους Δελφούς" σχετικά με τη δομή του DLL στη μνήμη:

Ένα DLL είναι μια βιβλιοθήκη, σε αντίθεση με μια εφαρμογή, δεν έχει ούτε στοίβα ούτε ουρά μηνυμάτων. Οι συναρτήσεις που τοποθετούνται σε ένα DLL εκτελούνται στο πλαίσιο της εφαρμογής κλήσης, χρησιμοποιώντας τη στοίβα της. Αλλά αυτές οι ίδιες λειτουργίες χρησιμοποιούν το τμήμα δεδομένων της βιβλιοθήκης και όχι το αντίγραφο της εφαρμογής. Λόγω αυτής της οργάνωσης του DLL, επιτυγχάνεται εξοικονόμηση μνήμης λόγω του γεγονότος ότι όλες οι εφαρμογές που εκτελούνται χρησιμοποιούν μία μονάδα DLL, χωρίς να συμπεριλαμβάνονται ορισμένες τυπικές λειτουργίες στις μονάδες τους. Συχνά, με τη μορφή ενός DLL, δημιουργούνται ξεχωριστά σύνολα συναρτήσεων, που συνδυάζονται σύμφωνα με το ένα ή το άλλο λογικό χαρακτηριστικό, παρόμοια με τον τρόπο με τον οποίο οι ενότητες σχεδιάζονται εννοιολογικά (με την έννοια μιας μονάδας) στο Pascal. Η διαφορά είναι ότι οι συναρτήσεις από τις μονάδες Pascal συνδέονται στατικά - στο στάδιο της σύνδεσης, και οι συναρτήσεις από τα DLL συνδέονται δυναμικά, δηλαδή κατά το χρόνο εκτέλεσης.

Δημιουργία DLL

Η δομή ενός DLL δεν διαφέρει πολύ από τη συνηθισμένη δομή μιας ενότητας στο Object Pascal. Ένα DLL πρέπει να ξεκινά με τη λέξη Library, ακολουθούμενη από το όνομα της βιβλιοθήκης. Οι λειτουργίες και οι διαδικασίες που θα παρέχει το DLL (εξαγωγή) σε άλλους χρήστες παρατίθενται μετά την οδηγία για τις εξαγωγές.

Για κάθε διαδικασία ή συνάρτηση, μπορείτε να καθορίσετε τον αριθμό της χρησιμοποιώντας την οδηγία Index. Εάν ο αριθμός λείπει, ο μεταγλωττιστής θα εκτελέσει αυτόματη ευρετηρίαση. Αντί για έναν αριθμό διαδικασίας, μπορείτε να χρησιμοποιήσετε ένα μοναδικό όνομα, το οποίο καθορίζεται χρησιμοποιώντας την οδηγία ονόματος. Εάν δεν προσδιορίζεται ούτε το όνομα της συνάρτησης ούτε ο αριθμός της, τότε οι Delphi θα το αντιληφθούν ως εξαγωγή με όνομα, το οποίο θα ταιριάζει με το όνομα της συνάρτησης.

Μια βιβλιοθήκη μπορεί επίσης να περιέχει κώδικα προετοιμασίας που θα εκτελεστεί όταν φορτωθεί. Τοποθετείται μεταξύ αρχής και τέλους. Ακολουθεί η γενική δομή του DLL:

LibraryFirst_Dll; χρήσεις<используемые модули>; <объявления и описания функций>εξαγωγές<экспортируемые функции> <описание процедур и функций>να αρχίσει<инициализационная часть>τέλος.

Θα δώσω παραδείγματα της περιγραφής των εξαγόμενων λειτουργιών στην ενότητα εξαγωγών:

Εξαγωγές Συνάρτηση1 ευρετήριο 2; Όνομα συνάρτησης2 "My_sqr"; συνάρτηση3;

Όπως ίσως μαντέψατε, το όνομα της συνάρτησης μπορεί να μην ταιριάζει με το όνομα εξαγωγής!!!

Χρήση DLL

Μια λειτουργική μονάδα που χρειάζεται να χρησιμοποιεί διαδικασίες και λειτουργίες από ένα DLL πρέπει να χρησιμοποιεί την εξωτερική οδηγία. Υπάρχουν δύο τρόποι χρήσης ενός DLL (δυναμικός και στατικός). Στην πρώτη περίπτωση, η εφαρμογή που καλεί τη συνάρτηση από το DLL γνωρίζει το όνομα της βιβλιοθήκης και το σημείο εισόδου της και υποτίθεται ότι η βιβλιοθήκη δεν αλλάζει. Στη δεύτερη περίπτωση, πριν χρησιμοποιήσετε το DLL, θα πρέπει να βεβαιωθείτε ότι υπάρχει η απαιτούμενη βιβλιοθήκη και ότι περιέχει την απαραίτητη υπορουτίνα.

Μπορείτε να εισαγάγετε μια υπορουτίνα με το όνομα και τον αριθμό της. Η αναζήτηση μιας υπορουτίνας κατά αριθμό είναι πιο γρήγορη, αλλά είναι πάντα βολική.

Τα παρακάτω είναι παραδείγματα εισαγωγής συναρτήσεων από το First_DLL μας, το οποίο καλύφθηκε στο παράδειγμα:

( εισαγωγή με καθορισμένο όνομα ) Λειτουργία ImportByName; εξωτερικό όνομα "First_DLL" "My_sqr"; ( εισαγωγή κατά ευρετήριο ) Λειτουργία ImportByOrdinal; εξωτερικό ευρετήριο "First_DLL" 2. (εισαγωγή με αρχικό όνομα) Λειτουργία Function3; εξωτερικό "First_DLL";

Εξετάσαμε τη στατική μέθοδο χρήσης ενός DLL. Αλλά σε ορισμένες περιπτώσεις, δεν είναι γνωστό εκ των προτέρων ποια βιβλιοθήκη θα απαιτηθεί, επομένως θα πρέπει να χρησιμοποιήσετε τη δυναμική μέθοδο:

Χρησιμοποιεί WinTypes, WinProcs, ... ; τύπος TMyProc = διαδικασία ; var Handle: THandle; MyImportProc: TMyProc; start Handle:=LoadLibrary("FirstDLL"); if Handle>=32 τότε (αν<=32 - ошибка! } begin @MyImportProc:=GetProcAddress(Handle,"My_sqr"); if MyImportProc<>μηδέν τότε ...... (εδώ χρησιμοποιούμε τη συνάρτηση που προκύπτει) τέλος; FreeLibrary(Handle); τέλος;

Αλλά κατά τη γνώμη μου, όλα όσα γράφονται εδώ δεν είναι πολύ ξεκάθαρα και θέλω πραγματικά ολοκληρωμένα παραδείγματα. Πάντα απογοητευόμουν όταν υπήρχαν λίγα παραδείγματα στα άρθρα, αλλά μόνο μία θεωρία, γι' αυτό φέρνω στην προσοχή σας ένα απλό παράδειγμα χρήσης ενός DLL.

Κάντε κλικ στο μενού Αρχείο -> Νέο και επιλέξτε DLL. Αποθηκεύστε το έτοιμο πρότυπο όπως προτείνεται με το όνομα Project1.dpr.

Παρακάτω είναι ο πλήρης κωδικός του:

έργο βιβλιοθήκης1; χρησιμοποιεί SysUtils,Classes. Συνάρτηση Συνάρτηση1(x,y:ακέραιος):ακέραιος; εξαγωγή; bginresult:=x+y; τέλος; Συνάρτηση Συνάρτηση2(x,y:real):real; εξαγωγή; vart:πραγματικό; start t:=exp(y*ln(x)); αποτέλεσμα:=t; τέλος; εξαγωγές Ευρετήριο Συνάρτησης1 1, Όνομα Συνάρτησης2 "My_sqr"; αρχή τέλος.

Υπάρχουν δύο συναρτήσεις εδώ, η πρώτη υπολογίζει το άθροισμα δύο αριθμών και εξάγεται με αριθμό και η δεύτερη υπολογίζει το x στη δύναμη του y και εξάγεται με το όνομα.

Τώρα ας δημιουργήσουμε ένα νέο έργο και ας το αποθηκεύσουμε με κάποιο άλλο όνομα, για παράδειγμα, DemoDLL. Ας τοποθετήσουμε δύο κουμπιά στη φόρμα, κάνοντας κλικ στο πρώτο θα καλέσετε την πρώτη διαδικασία και κάνοντας κλικ στο δεύτερο θα καλέσετε τη δεύτερη. Εδώ είναι ο πλήρης κώδικας για αυτό το έργο επίδειξης:

επίδειξη μονάδας? Η διεπαφή χρησιμοποιεί Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls. τύπος TForm1 = class(TForm) Button1: TButton; Κουμπί 2: TButton; διαδικασία Button1Click(Αποστολέας: TObject); διαδικασία Button2Click(Αποστολέας: TObject); ιδιωτικές ( Ιδιωτικές δηλώσεις ) δημόσιο ( Δημόσιες δηλώσεις ) τέλος; var Form1: TForm1; υλοποίηση ($R *.DFM) συνάρτηση ImportSumm(x,y:integer):integer; εξωτερικός δείκτης "Project1" 1. //εισαγωγή κατά αριθμό συνάρτηση ImportSqr(x,y:real):real; εξωτερικό όνομα "Project1" "My_sqr"; //διαδικασία εισαγωγής με όνομα TForm1.Button1Click(Sender: TObject); vart:πραγματικό; start //Μάθετε πόσα δύο στην τρίτη δύναμη θα είναι t:=ImportSqr(2,3); Showmessage(FloatTostr(t)); τέλος; διαδικασία TForm1.Button2Click(Αποστολέας: TObject); vart:integer; start //Μάθετε πόσο 10+10 θα είναι t:=ImportSumm(10,10); Showmessage(IntTostr(t)); τέλος; τέλος.

Προγραμματιστής Delphi, MySQL. Ανώτερη εκπαίδευση. Ειδικότητα: λογισμικό πληροφορικής.