Καλώντας εξωτερικές βιβλιοθήκες DLL από τα scripts της WME

(Σημείωση: αυτή η λειτουργία παρέχεται για στους χρήστες με εμπειρία προγραμματισμού)

Δήλωση

Μπορείτε μέσω των scripts της WME να καλέσετε εξωτερικές συναρτήσεις από βιβλιοθήκες DLL. Αυτό σημαίνει ότι μπορείτε να καλέσετε τις Win32 API συναρτήσεις ή να γράψετε τις δικές σας βιβλιοθήκες DLL.

Για να χρησιμοποιήσετε μία εξωτερική συνάρτηση πρέπει πρώτα να τη δηλώσετε. Η σύνταξη της δήλωσης είναι η παρακάτω:

external "dll_name" [calling_convention] [return_type] function_name ( [parameters] );

(τα τμήματα που βρίσκονται μέσα στις αγκύλες είναι προαιρετικά)

dll_name - Το όνομα της βιβλιοθήκης μέσα σε εισαγωγικά. Μπορεί επίσης να περιλαμβάνει την σχετική ή απόλυτη διαδρομή στους φακέλους (δεν συνίσταται). Παρακαλώ δείτε τα έγγραφο βοηθείας του Win32 API για πληροφορίες πως τα Windows αναζητούν μία βιβλιοθήκη DLL.

calling_convention - Αυτό ορίζει ποια calling convention η συγκεκριμένη συνάρτηση χρησιμοποιεί. Μπορεί να είναι stdcall ή cdecl. Αν δεν ορίσετε εσείς κάποια τότε η WME θα χρησιμοποιήσει την stdcall. Η stdcall convention χρησιμοποιείται από το Win32 API ενώ οι δικές σας βιβλιοθήκες DLL γραμμένες στη C/C++ πιθανότατα θα χρησιμοποιούν την cdecl convention. Παρακαλώ ελέγξτε το έγγραφο βοηθείας του μεταγλωττιστή σας για περισσότερες πληροφορίες σχετικά με τις calling conventions.

return_type - Ορίζει το είδος της τιμής που επιστρέφει η συνάρτηση. Αν δεν επιστρέφει καμία τιμή (το είδος της επιστροφής είναι void) ή αν δεν θέλετε να χρησιμοποιήσετε αυτή την τιμή δεν χρειάζεται να ορίσετε και το είδος της. Δείτε παρακάτω για τη λίστα με τα υποστηριζόμενα είδη δεδομένων.

function_name - Αυτό είναι το όνομα της συνάρτησης όπως εξάγεται από την βιβλιοθήκη DLL. Πρέπει να είναι ακριβές αλλιώς η WME δεν θα μπορεί να την καλέσει.   
 - Σημείωση 1: Αν γράφετε το DLL στη γλώσσα C++ βεβαιωθείτε ότι έχετε ορίσει την συνάρτηση ως extern "C" αλλιώς η DLL θα εξάγει ένα "decorated" C++ όνομα.
 - Σημείωση 2: Αν δηλώσετε μία Win32 API συνάρτηση θυμηθείτε ότι όλες οι συναρτήσεις δουλεύουν σε δύο κατηγορίες strings, ANSI και Unicode που σημαίνει ότι τα windows DLL εξάγουν δύο συναρτήσεις: FunctionNameA (ANSI) και FunctionNameW (Unicode). Η WME προς το παρόν δεν υποστηρίζει Unicode οπότε πρέπει να χρησιμοποιήσετε τις συναρτήσεις A (ANSI).

parameters - Αυτή είναι μια λίστα με παραμέτρους που ξεχωρίζουν με κόμμα. Οι παράμετροι ορίζονται από το είδος που ακολουθεί (προαιρετικά) το όνομά τους. Δεν χρειάζεται να ορίσετε ονόματα καθώς δεν χρησιμεύουν σε τίποτα. Δείτε παρακάτω για τη λίστα με τα διαθέσιμα είδη δεδομένων.

Είδη δεδομένων

Η WME σας επιτρέπει να περνάτε μόνο πρωταρχικά είδη στις συναρτήσεις DLL. Παρότι η WME χρησιμοποιεί μεταβλητές στις οποίες δεν έχει οριστεί κάποιο είδος δεδομένων, μετατρέπονται στο ζητούμενο πρωταρχικό είδος όταν περνούν σε μία συνάρτηση DLL.

Τα υποστηριζόμενα είδη δεδομένων είναι:

int 32 bit ακέραιος αριθμός, ισοδύναμος με int, long ή DWORD
bool λογική τιμή που μπορεί να είναι αληθές (true) ή ψευδές (false)
byte τιμή 8 bit, ισοδύναμη με BYTE ή unsigned char
string πίνακας που αποτελείται από χαρακτήρες 8 bit, ισοδύναμος με char* ή LPSTR ή LPCSTR (δείτε παρακάτω)
float τιμή 32 bit με κινητή υποδιαστολή, ισοδύναμη με float ή FLOAT
double τιμή 64 bit με κινητή υποδιαστολή, ισοδύναμη με double
membuffer δείκτης μνήμης 32 bit: πρέπει να εκπροσωπείται από το αντικείμενο MemBuffer της WME

Μπορείτε επίσης να χρησιμοποιήσετε και τα είδη δεδομένων short και long που είναι συνώνυμα με το int.

Οι τιμές στα WME scripts έχουν μεταβλητό μέγεθος που εξαρτάται από την τιμή που περιέχουν. Ορισμένες όμως συναρτήσεις DLL επιστρέφουν μία τιμή ή ένα πίνακα σε ένα προκαθορισμένο μέγεθος προσωρινού αποθηκευτικού χώρου. Σε αυτή την περίπτωση δεν μπορείτε να χρησιμοποιήσετε τις απλές μεταβλητές αλλά θα πρέπει να δημιουργήσετε ένα αντικείμενο String και να ορίσετε το απαιτούμενο μέγεθος του:

var MyFixedString = new String(256); // αυτό θα δημιουργήσει ένα αντικείμενο string με μέγεθος αποθηκευτικού χώρου 255 χαρακτήρες

Σημείωση: Μπορείτε να ελέγξετε το μέγεθος μιας τιμής χρησιμοποιώντας την ιδιότητα Capacity του αντικειμένου string.

Εσωτερικά δεδομένα των DLL

Όταν η WME καλεί κάποια εξωτερική συνάρτηση DLL, φορτώνει το DLL αμέσως πριν την κλήση και το ελευθερώνει μετά το τέλος της. Οπότε το DLL δεν μπορεί να κρατήσει κανένα εσωτερικό δεδομένο μεταξύ διαδοχικών κλήσεων στις συναρτήσεις του καθώς κατά την απελευθέρωσή του χάνονται όλα. Αυτό το πρόβλημα μπορεί να ξεπεραστεί με την μόνιμη φόρτωση του DLL μέσω κάποιου script με την συνάρτηση LoadLibraryA API. Πρέπει όμως να θυμάστε ότι ο παίκτης μπορεί να αποθηκεύσει το παιχνίδι ή να φορτώσει μια παλαιότερη θέση οποιαδήποτε στιγμή, οπότε το DLL θα ελευθερωθεί. Μπορείτε να χρησιμοποιήσετε τους χειριστές γεγονότων BeforeSave και AfterLoad για την αποθήκευση και επανάκτηση των δεδομένων πριν την αποθήκευση του παιχνιδιού και μετά την φόρτωσή του.

Πέρασμα structures από και προς τις συναρτήσεις DLL

Ορισμένες από τις συναρτήσεις API και πιθανότατα και δικές σας DLL συναρτήσεις μπορεί να απαιτούν την τροφοδότηση με structures. Για αυτό τον σκοπό η WME περιλαμβάνει το είδος αντικειμένου MemBuffer. Με την δημιουργία ενός τέτοιου αντικειμένου μέσω ενός script δεσμεύετε συγκεκριμένο χώρο στη μνήμη που στη συνέχεια μπορείτε να τροφοδοτήσετε στη συνάρτηση DLL. Τα αντικείμενα αυτά διαθέτουν ορισμένες μεθόδους για την εγγραφή/ανάγνωση δεδομένων σε διάφορα είδη από και προς αυτά εξομοιώνοντας έτσι το "struct" που είναι γνωστό από άλλες γλώσσες προγραμματισμού. Δείτε τον οδηγό αναφοράς για το Αντικείμενο MemBuffer για περισσότερες λεπτομέρειες.

Προειδοποίηση

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

Παράδειγμα

Το ακόλουθο παράδειγμα δείχνει τη δήλωση DLL και τη χρήση διαφόρων συναρτήσεων Win32 API μέσω ενός WME script.

// δήλωση
external "user32.dll" MessageBeep(int uType);
external "kernel32.dll" long GetTempPathA(int nBufferLength, string lpBuffer);
external "kernel32.dll" int LoadLibraryA(string);
external "kernel32.dll" FreeLibrary(int);

function MyDllTest()
{
  // Η συνάρτηση MessageBeep παίζει έναν ήχο
  MessageBeep(0);

  // Η συνάρτηση GetTempPath επιστρέφει τον προσωρινό φάκελο των Windows
  var TempPath = new String(256);
  GetTempPathA(TempPath.Capacity, TempPath);
  Game.Msg("Ο προσωρινός φάκελος των windows είναι ο: " + TempPath);

  // Φόρτωση του DLL και άμεση αποφόρτωσή του
  var hDll = LoadLibraryA("MyDll.dll");
  FreeLibrary(hDll);
}