Autres articles / Other articles

Gestion des paramètres entre eForth et l'API Windows

publication: 1 décembre 2024 / mis à jour 1 décembre 2024

Read this page in english

 


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:

CeForthtaille
pointerptr8 octet
BYTEi81 octet
DWORDi324 octets
LONGi324 octets
UINTi324 octets
WORDi162 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