Gestion des paramètres entre eForth et l'API Windows
publication: 1 décembre 2024 / mis à jour 1 décembre 2024
La gestion des paramètres entre eForth et l'API Windows est un point sensible. Beaucoup de fonctions du langage C exigent un typage des donnés: booléen, chaînes de caractères, valeurs en 8, 16, 32 ou 64 bits. Nous allons explorer en détail cette gestion des paramètres.
Passage des paramètres par la pile de données
On le rappelle, la version eForth Windows 7.0.7.21 et suivantes gèrent toutes les données sur les piles de données et de retour au format entiers 64 bits.
eForth Windows peut être étendu en créant de nouveaux mots FORTH interfacés à des fonctions de l'API Windows. Exemple:
only forth windows definitions \ returns the system's time and date z" GetLocalTime" 1 Kernel32 GetLocalTime ( addr -- )
Ici, on définit un nouveau mot GetLocalTime
qui utilise la fonction GetLocalTime
disponible dans le fichier kernel32.dll.
Au fil des versions de Windows, les fonctionnalités de kernel32.dll ont évolué pour s'adapter aux architectures 64 bits, offrant ainsi une meilleure gestion des grands volumes de données.
La capacité d'une fonction à gérer des données 64 bits dépend en grande partie du type de données qu'elle manipule. Certaines fonctions sont spécifiquement conçues pour travailler avec des entiers 64 bits (int64_t), des pointeurs 64 bits, etc.
On définit la structure associée à GetLocalTime
:
\ Definition in C language: \ typedef struct _SYSTEMTIME { \ WORD wYear; \ WORD wMonth; \ WORD wDayOfWeek; \ WORD wDay; \ WORD wHour; \ WORD wMinute; \ WORD wSecond; \ WORD wMilliseconds; \ } SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; stuct SYSTEMTIME i16 field ->wYear i16 field ->wMonth i16 field ->wDayOfWeek i16 field ->wDay i16 field ->wHour i16 field ->wMinute i16 field ->wSecond i16 field ->wMilliseconds
Ici on définit la structure SYSTEMTIME
calquée sur sa définition en langage C, dont le code
source a été mis en commentaire. Ce code source en C ne sert que pour information. Une fois
la structure testée avec succès, on peut supprimer ce code en C.
Exemple d'utilisation:
create sysTime
SYSTEMTIME allot
: dispTime ( -- )
sysTime GetLocalTime drop
systime ->wHour UW@ .
systime ->wMinute UW@ .
systime ->wSecond UW@ .
;
Ici, le mot dispTime
va afficher l'heure extraite du système. Dans la définition de dispTime
, on accède
aux champs de la structure sysTime avec des accesseurs pointant vers des données au format 16 bits non signées.
L'adresse de la structure sysTime
est passée au mot GetLocalTime
au format des
données de la pile de données, ici au format 64 bits.
En retour, GetLocalTime
empile un flag booléen qui sera toujours une donnée 64 bits dans la pile de données Forth.
Donc, sur un système Windows 64 bits, avec eForth Windows 7.0.7.21+, tous les échanges de données par la pile de données seront systématiquement au format 64 bits.
La seule chose qui peut être nécessaire, c'est de limiter l'intervalle de définition d'une donnée. Ici, le code source, en langage C de la fonction CreateFontA:
HFONT CreateFontA( [in] int cHeight, [in] int cWidth, [in] int cEscapement, [in] int cOrientation, [in] int cWeight, [in] DWORD bItalic, [in] DWORD bUnderline, [in] DWORD bStrikeOut, [in] DWORD iCharSet, [in] DWORD iOutPrecision, [in] DWORD iClipPrecision, [in] DWORD iQuality, [in] DWORD iPitchAndFamily, [in] LPCSTR pszFaceName );
Ici, le paramètre bItalic doit être un flag booléen, donc une valeur dans l'intervale [0,1]. En C, la donnée est typée DWORD. Un DWORD est un raccourci pour "Double Word". Il représente généralement un entier non signé de 32 bits, soit 4 octets.
eForth empile une valeur 64 bits pour ce paramètre bItalic, la fonction en C dans l'API va tronquer cette valeur 64 bits au moment d'injecter cette valeur dans la fonction CreateFontA.
Taille des données dans les structures
L'API Windows réalise beaucoup d'échange de données en utilisant des structures. Ces structures existent sous Windows et Linux. Pour ce qui nous concerne, on ne s'intéressera qu'aux structures à gérer entre eForth et Windows.
Commençons par une structure très simple, la structure RECT
:
\ typedef struct tagRECT { \ LONG left; \ LONG top; \ LONG right; \ LONG bottom; \ } RECT, *PRECT, *NPRECT, *LPRECT; struct RECT i32 field ->left i32 field ->top i32 field ->right i32 field ->bottom
Dans cette structure RECT
, nous n'avons à gérer que quatre champs de type LONG,
donc on utilise i32
pour définir chaque champ de cette structure.
Ici, une structure aux données avec des formats variés:
\ typedef struct tagBITMAPINFOHEADER { \ DWORD biSize; \ LONG biWidth; \ LONG biHeight; \ WORD biPlanes; \ WORD biBitCount; \ DWORD biCompression; \ DWORD biSizeImage; \ LONG biXPelsPerMeter; \ LONG biYPelsPerMeter; \ DWORD biClrUsed; \ DWORD biClrImportant; \ } BITMAPINFOHEADER struct BITMAPINFOHEADER i32 field ->biSize \ must be i32 ?? i32 field ->biWidth i32 field ->biHeight i16 field ->biPlanes i16 field ->biBitCount i32 field ->biCompression i32 field ->biSizeImage i32 field ->biXPelsPerMeter i32 field ->biYPelsPerMeter i32 field ->biClrUsed i32 field ->biClrImportant
Pour chaque type de données, on utilise le paramètre i8
, i16
ou i32
correspondant à la taille de la donnée à gérer:
C | eForth | taille |
---|---|---|
pointer | ptr | 8 octet |
BYTE | i8 | 1 octet |
DWORD | i32 | 4 octets |
LONG | i32 | 4 octets |
UINT | i32 | 4 octets |
WORD | i16 | 2 octets |
Dans certains cas, l'analyse peut s'avérer complexe:
\ typedef struct tagMSG { \ HWND hwnd; \ UINT message; \ WPARAM wParam; \ LPARAM lParam; \ DWORD time; \ POINT pt; \ DWORD lPrivate; \ } MSG, *PMSG, *NPMSG, *LPMSG; struct MSG ptr field ->hwnd i32 field ->message i16 field ->wParam i32 field ->lParam i32 field ->time POINT field ->pt i32 field ->lPrivate
Ici, l'analyse des types WPARAM et LPARAM doit se faire par analyse du code source en C dans lequel est définie la structure.
Le type POINT
est une structure. ici, on a affaire à une structure imbriquée.
De nombreuse clés sont expliquées ici:
https://learn.microsoft.com/fr-fr/windows/win32/winprog/windows-data-types
Legal: site web personnel sans commerce / personal site without seling