HDAPI en Visual Basic


Présentation Générale

Utilisation d'HDAPI en : [C/C++] [ Delphi] [Visual Basic]


'///////////////////////////////////////////////////////////////////////////
'// Démo HDAPI Visual Basic
'///////////////////////////////////////////////////////////////////////////
'// 08/11/2002
'//
'// Copyright (c) 2002, E. Ravon (Bat)
'//
'// Auteur : manu_bat_manu@yahoo.fr
'//
'// Démonstration minimale de l'utilisation d'HDAPI en Delphi
'//
'// Ce code est un exemple d'accès en Visual Basic aux données du logiciel HelloDOC
'// Il utilise la bibliothèque HDAPI.
'//
'// Ce code a été développé pour HelloDOC Etendu 4.56.791
'// Ainsi que pour la version d'HDAPI.DLL associée.
'//
'// Il a été testé avec HD 4.56 étendu
'// Son fonctionnement n'est pas guaranti avec des versions plus récentes d'HD
'//
'//
'// HelloDOC est développé par Imagine Editions.
'// Windows est une marque de Microsoft Corporation
'////////////////////////////////////////////////////////////////////////////


Fichiers : HD_VB.zip (source)

Version exécutable

Fenêtre principale

  • Cet exemple permet d'exporter le contenu de l'Agenda du jour, de façon identique à l'exemple en C.
  • Il ne gère pas :
    • La mémorisation en Base De Registre des paramètres du cabinet.

Sources

  • Form1.frm, Module1.bas

La partie détaillée ici est l'import des fonctions d'HDAPI. Hormis HDAPI.DLL et la documentation (hdapi.pdf) associée, rien d'autre n'est indispensable. Le fichier hdapi.h peut être utilisé comme référence, mais ne sert pas directement.

Toutes les fonctions exportées par HDAPI peuvent être incluses dans un projet Visual Basic. Ici, le fichier Form1.frm contient l'utilisation d'HDAPI. Le fichier Module1.bas contient toutes les définitions relatives à HDAPI.

On détaille ensuites les différents éléments spécifiques à l'utilisation en Visual Basic.

  • Type de données personnalisés
    Visual Basic ne permet pas de définir des types 'simples' de données personnalisées (typedef en C). Ici, on a choisi de remplacer directement les types redéfinis (ex : USHORT) par leurs équivalents en Visual Basic lorsqu'ils existent. Cette solution peut poser un certain nombre de contraintes (de mise à jour), mais reste la plus simple.

    Les types supportés par Visual Basic sont les suivants :
  • Nom
    Nombre d'octets
    Plage de valeurs
    Byte 1
    0 à 255
    Boolean 2 True ou False
    Integer 2 -32,768 à 32,767
    Long 4 -2,147,483,648 à 2,147,483,647
    Single 4 -3.402823E38 à -1.401298E-45 (pour les valeurs négatives) 1.401298E-45 à 3.402823E38 (pour les valeurs positives)
    Double 8 -1.79769313486232E308 à -4.94065645841247E-324 (pour les valeurs négatives) 4.94065645841247E-324 à 1.79769313486232E308 (pour les valeurs positives)


Hormis le type Byte, tous les types sont signés, ce qui pourra poser des problèmes dans certains cas (USHORT par ex).

  • Enumarations (enum)
    Elles sont sensiblement identiques à celles présentes en C.
  • Constantes
    Elles sont définies par Public Const
  • Fonctions
    • Pour des fonctions simples ne retournant pas de valeurs [en C : void fonction(param);] on utilisera une Sub
      • Public Declare Sub HDCloseSession Lib "HDAPI" ()
    • Pour des fonctions retournant une valeur [en C : type fonction(param);] on utilisera une Function
      • Public Declare Function HDOpenSession Lib "HDAPI" (network As Boolean) As Boolean
  • Structures
    Certaines fonctions nécessitent des types de données particuliers définis dans HDAPI.DLL. Ces types se retrouvent dans HDAPI.H, et doivent être redéfinis, de façon équivalente en Visual Basic.
    C'est le point faible. HDAPI utilise des structures alignées sur des octets (pour gagner de la place lors du stockage). Visual Basic n'est pas capable de représenter de telles structures. Visual Basic ne peut réaliser des alignements que sur des mots de 32 bits.
    En pratique :
    • En C, lorsque l'on utilise l'alignement sur des octets (cas d'HDAPI) (#pragma pack(1))
struct ma_structure{
int z;
char data;
short val;
char c;
}
sera représenté en mémoire par :
    Adresse Donnée
    0
    int z
    1
    int z
    2
    int z
    3
    int z
    4
    data
    5
    val
    6
    val
    7
    c

  • En Visual Basic, l'alignement se fait forcément sur des mots de 32 bits. Cette méthode permet de commencer chaque élément sur une adresse multiple de 4, ce qui améliore les performances sur un système 32 bits. Par contre il y a des emplacements mémoire non-utilisés (padding) qui sont donc perdus. La même structure sera représenté comme ceci :

Adresse Donnée
0
int z
1
int z
2
int z
3
int z
4
data
5
--
6
--
7
--
8
val
9
val
10
--
11
--
12
c
13
--
14
--
15
--
  • Si on range directement les données fournies par HDAPI dans une structure du Visual Basic, les données ne vont pas correspondre. (Si on demande le contenu de data depuis Visual Basic, on aura la donnée formée par les 32 bits data, val et c). Il n y a pas de manière 'simple' pour résoudre ce problème en Visual Basic. On peut :
    • Etendre la structure récupérée d'HDAPI à la main (pour la faire correspondre avec celle de Visual Basic) et l'utiliser directement. La compacter à la main, lorsque l'on envoie la structure à HDAPI.
      Cette méthode est la plus efficace, cependant elle est lourde à mettre en ouvre, car il faut pour chaque structure évaluer les zones qu'il va falloir étendre/compacter en fonction des divers éléments de la structure. Cette méthode est très lourde pour de grosses structures. Elle demande aussi beaucoup de travail lorsqu'il y a une modification des données.
    • Utiliser un fichier. Oui, bien que cela ne soit pas naturel, en passant par un fichier on résoud de manière quasiment générique le problème. Lorsque Visual Basic écrit/lit une structure dans un fichier, il l'écrit/lit comme si elle était alignée sur des octets (donc sans padding).
      • Pour convertir une structure HDAPI vers Visual Basic, on utilisera :
        '=============================================
        Dim data(Len(data_ag)) As Byte
        MoveMemory data(0), ByVal ag, Len(data_ag)
        'On copie les données "brutes" dans data
        Open "TMP.TMP" For Binary As #2
        Put #2, 1, data
        Get #2, 1, data_ag
        Close #2
        '=============================================

        On copie d'abord l'ensemble des octets formant la structure (sans distinction, sous forme de tableau d'octets) dans un fichier. On copie donc directement ce qu'a retourné HDAPI dans un fichier. On demande ensuite à Visual Basic de relire ces données comme une structure. La conversion va donc se faire naturellement.
      • Pour convertir une structure Visual Basic vers HDAPI, on utilisera :
        '=================================================
        Dim data2(Len(data_pat)) As Byte
        Open "TMP.TMP" For Binary As #2
        Put #2, 1, data_pat
        Get #2, 1, data2
        Close #2
        MoveMemory ByVal pat, data2(0), Len(data_pat)
        '=================================================

        On copie la structure dans un fichier, Visual Basic va donc naturellement la copier sous forme alignée sur des octets. On relit ensuite l'ensemble des données sous forme de tableau que l'on passe directement à HDAPI.
    • L'énorme désavantage du fichier se situe évidemment sur la lenteur générée par cette opération.
  • Pointeurs
    Il n'existe pas de pointeurs en Visual Basic. Etant donné que beaucoup de fonctions d'HDAPI manipulent des pointeurs sur des blocs mémoire, ou des structures, il est nécessaire de trouver une solution.
    On représente les pointeurs sous forme de Long. On utilise ensuite l'API Win32
    Declare Sub MoveMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    qui permet de copier un bloc mémoire dans un autre en ayant uniquement son adresse (donc un pointeur).
    De même en détournant : Declare Function GetAddrOf Lib "KERNEL32" Alias "MulDiv" (nNumber As Any, Optional ByVal nNumerator As Long = 1, Optional ByVal nDenominator As Long = 1) As Long de son utilisation, on peut obtenir l'adresse d'une variable.
  • Chaines de caractères
    Sous Visual Basic, les chaines de caractères sont de type String, type bien plus compliqué qu'en C.
    En C, un chaine est un ensemble d'octets (un tableau) terminé par la valeur 0 (caractère de valeur ASCII 0 et non '0'). Les chaines peuvent être en ASCII ou en UNICODE
    En Visual Basic, un chaine stocke en plus de la chaine, sa longueur, et d'autres paramètres. Les chaines sont en UNICODE.
    • Pour convertir une chaine d'HDAPI vers Visual Basic, on récupère les octets 1 à 1 dans le tableau jusqu'au 0 terminal. Cette opération est réalisée par : Private Function to_string(cle() As Byte) As String
    • Pour envoyer une chaine Visual Basic à HDAPI, on utilise une chaine standard à laquelle on rajoute le caractère 0 [chr$(0)]. Visual Basic se charge de la transcription de l'UNICODE.