IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API, COM et SDKs Delphi Discussion :

Conversion Header C pour utilisation DLL


Sujet :

API, COM et SDKs Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut Conversion Header C pour utilisation DLL
    Bonjour à tous,

    Je tente de convertir un header C win32 pour utiliser un DLL.

    A priori, ça ne fonctionne pas très bien. Si quelqu'un voit les erreurs... Car le C, n'est vraiment pas ma tasse de thé...

    Voici le header C:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
     
     
    #ifdef __cplusplus
    extern "C" {
    #endif
     
    typedef enum
    {
        WPS_OK = 0,
        WPS_ERROR_SCANNER_NOT_FOUND = 1,
        WPS_ERROR_WIFI_NOT_AVAILABLE = 2,
        WPS_ERROR_NO_WIFI_IN_RANGE = 3,
        WPS_ERROR_UNAUTHORIZED = 4,
        WPS_ERROR_SERVER_UNAVAILABLE = 5,
        WPS_ERROR_LOCATION_CANNOT_BE_DETERMINED = 6,
        WPS_ERROR_PROXY_UNAUTHORIZED = 7,
        WPS_ERROR_FILE_IO = 8,
        WPS_ERROR_INVALID_FILE_FORMAT = 9,
        WPS_ERROR_TIMEOUT = 10,
        WPS_NOT_APPLICABLE = 11,
        WPS_GEOFENCE_ERROR = 12,
        WPS_NOMEM = 98,
        WPS_ERROR = 99
    } WPS_ReturnCode;
     
    typedef struct
    {
        const char* username;
        const char* realm;
    } WPS_SimpleAuthentication;
     
    typedef enum
    {
        WPS_NO_STREET_ADDRESS_LOOKUP,
        WPS_LIMITED_STREET_ADDRESS_LOOKUP,
        WPS_FULL_STREET_ADDRESS_LOOKUP
    } WPS_StreetAddressLookup;
     
    typedef struct
    {
        char* name;
        char code[3];
    } WPS_NameCode;
     
    typedef struct
    {
        char* street_number;
        char** address_line;
        char* city;
        char* postal_code;
        char* county;
        char* province;
        WPS_NameCode state;
        char* region;
        WPS_NameCode country;
    } WPS_StreetAddress;
     
    typedef enum
    {
        WPS_LOCATION_TYPE_2D,
        WPS_LOCATION_TYPE_3D
    } WPS_LocationType;
     
    typedef struct
    {
        //@{
        double latitude;
        double longitude;
        //@}
        double hpe;
        unsigned short nap;
        double speed;
        double bearing;
        WPS_StreetAddress* street_address;
        unsigned short ncell;
        unsigned short nsat;
        double altitude;
        WPS_LocationType type;
        unsigned long age;
    } WPS_Location;
     
     
    WPSAPI_EXPORT WPS_ReturnCode WPSAPI_CALL
    WPS_location(const WPS_SimpleAuthentication* authentication,
                 WPS_StreetAddressLookup street_address_lookup,
                 WPS_Location** location);
     
    WPSAPI_EXPORT void WPSAPI_CALL
    WPS_free_location(WPS_Location*);
     
     
    #ifdef __cplusplus
    }
    #endif
    Voici ma tentative de conversion:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
     
    WPS_StreetAddressLookup = (
     WPS_NO_STREET_ADDRESS_LOOKUP,
     WPS_LIMITED_STREET_ADDRESS_LOOKUP,
     WPS_FULL_STREET_ADDRESS_LOOKUP
    );
     
    WPS_ReturnCode = (
      WPS_OK = 0,
      WPS_ERROR_SCANNER_NOT_FOUND = 1,
      WPS_ERROR_WIFI_NOT_AVAILABLE = 2,
      WPS_ERROR_NO_WIFI_IN_RANGE = 3,
      WPS_ERROR_UNAUTHORIZED = 4,
      WPS_ERROR_SERVER_UNAVAILABLE = 5,
      WPS_ERROR_LOCATION_CANNOT_BE_DETERMINED = 6,
      WPS_ERROR_PROXY_UNAUTHORIZED = 7,
      WPS_ERROR_FILE_IO = 8,
      WPS_ERROR_INVALID_FILE_FORMAT = 9,
      WPS_ERROR_TIMEOUT = 10,
      WPS_NOT_APPLICABLE = 11,
      WPS_GEOFENCE_ERROR = 12,
      WPS_NOMEM = 98,
      WPS_ERROR = 99);
     
    WPS_LocationType = (WPS_LOCATION_TYPE_2D, WPS_LOCATION_TYPE_3D);
     
    WPS_SimpleAuthentication = Record
      username: PChar;
      realm: PChar;
    End;
     
    WPS_NameCode = Record
      name: PChar;
      code: array[0..2] of Char;
    End;
     
    PPchar = array [0..0] of PChar;
     
    WPS_StreetAddress = Record
      street_number: PChar;
      address_line: PPChar;  
      city: PChar;
      postal_code: PChar;
      county: PChar;
      province: PChar;
      state: WPS_NameCode;
      region: PChar;
      contry: WPS_NameCode;
     
    End;
     
    TWPS_Location = record
      hpe : double;      // Précision en mètres
      nap: word;         // Nb de point d'accès utilisés
      speed: double;     // Vitesse  en Km/h
      bearing: double;  // Rotation
      street_addresse: ^WPS_StreetAddress;
      ncell: Word;     // Nb d'antennes GSM utilisées
      nsat: Word;      // Nb de satellites GPS utilisés
      altitude: double;
      loctype : WPS_LocationType;
      age: LongInt;
      latitude : double;
      longitude : double;
    end;
    PTWPS_Location = ^TWPS_Location;
     
     
    function WPS_location (
      const authentication :WPS_SimpleAuthentication;
      street_address_lookup: WPS_StreetAddressLookup;
      location: PTWPS_Location):WPS_ReturnCode; stdcall; external 'wpsapi.dll';
     
    procedure WPS_free_location (location: PTWPS_Location) stdcall; external 'wpsapi.dll';
     
    procedure GetWifiLoc;
    var
      authentication : WPS_SimpleAuthentication;
      location: PTWPS_location;
      retour : WPS_ReturnCode;
    Begin
      authentication.username := 'XXXXXX';
      authentication.realm := 'YYYYY';
     
      retour := WPS_location(&authentication, PS_LIMITED_STREET_ADDRESS_LOOKUP, &location);
      if retour = WPS_OK then begin
       WPS_free_location(&location);
      end;
     
    End;
    En particulier, mes questions portent sur les points suivants:

    Un doit-il être traduit par un ou par un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    c : array[0..0] of PChar
    ?

    Quelle est la signification du //@ dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    //@{
        double latitude;
        double longitude;
        //@}
    Sachant que dans la documentation, ces deux champs sont à la fin de la structure mais que dans le header ils sont en tête.
    Voici la doc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    9.3 WPS_Location Struct Reference
    #include <wpsapi.h>
    Data Fields
    • double hpe
    • unsigned short nap
    • double speed
    • double bearing
    • WPS_StreetAddress  street_address
    • unsigned short ncell
    • unsigned short nsat
    • double altitude
    • WPS_LocationType type
    • unsigned long age
    • double latitude
    • double longitude
    Enfin, au niveau de l'appel de la fonction en C
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    WPS_location(const WPS_SimpleAuthentication* authentication,
                 WPS_StreetAddressLookup street_address_lookup,
                 WPS_Location** location);
    les traductions de déclaration et d'appel Delphi sont-elles ok ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    // Déclaration
    function WPS_location (
      const authentication :WPS_SimpleAuthentication;
      street_address_lookup: WPS_StreetAddressLookup;
      location: PTWPS_Location):WPS_ReturnCode; stdcall; external 'wpsapi.dll';
     
    // Appel
    retour := WPS_location(&authentication, WPS_LIMITED_STREET_ADDRESS_LOOKUP, &location);
    Merci d'avance de vos avis.

    André.

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 082
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 082
    Par défaut
    Delphi Ansi ou Unicode (2009 à XE...)

    **^char serait un ^^Char ou ^PChar
    Par prudent PAnsiChar au lieu de PChar
    En tout cas cela ne sera pas un array[0..0] car un tableau à taille fixe n'est pas un pointeur contrairement à un tableau dynamique

    **char doit effectivement désigné un tableau de chaine, un 0 indiquant une fin de chaine, un double 0 indiquant la fin du tableau en ANSI
    En UniCode, en théorie, c'est double 0 pour de fin chaine, et double-double 0 pour fin de tableau.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Expert éminent
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    pour WPS_location il y a des erreurs.

    le principe est toujours le même, l'étoile du C peut être remplacée par "const", "var" ou un "^type". ça dépend essentiellement du contexte.

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    WPS_location(const WPS_SimpleAuthentication* authentication,
                 WPS_StreetAddressLookup street_address_lookup,
                 WPS_Location** location);

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    WPS_location(const authentication: WPS_SimpelAuthentication;
      street_address_lookup: WPS_StreetAddressLookup;
      var location : PWPS_Location);
     
    var
      location: PWPS_location;
    begin
      WPS_location(authentication, lookup, location);
    end;
    j'imagine que la fonction retourne dans "location" un pointeur vers un WPS_location, le mot clé "var" est alors indiqué.

    mais si ce paramètre peut-être nul, il vaut mieux passer par un PPWPS_location (pointeur de pointeur de structure).
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    Merci pour vos précisions.

    Alors effectivement, pour le char**, c'est bien du ^PAnsichar.

    Quant au PWPS_location ou PPWPS_location, le PPWPS_location fonctionne. Je récupère bien des informations correctes dans PPWPS_location^, sauf justement pour un char** sur les deux que comporte la structure.

    Et j'ai aussi une exception qui se produit en sortant de la procédure GetWifiLoc.

    Je continue mes tests et investigations.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    Pour l'un des deux char** non renseigné, c'est ok. Il s'agit de la codification du "state" au sens adresse US. Il n'est donc effectivement pas initialisé puisque mes test sont fait en France, d'où les étranges valeurs.

    Pour l'exception en sortie de procédure, tout simplement la convention d'appel qui était mauvaise : j'avais mis stdcall au lieu de cdecl !


    Merci !

  6. #6
    Membre Expert Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Par défaut
    Il me semble aussi qu'il faut utiliser la directive
    pour encoder les enum sur 4 octets (ce qui est le defaut en C), alors que delphi adapte la taille en fonction du nombre d'elements.
    Je crois aussi qu'il faut mettre les "record" en "packed record", car je ne crois pas qu'ils soient alignés en C.

    J'espere ne pas t'envoyer dans une mauvaise direction, que quelqu'un me corrige si je me trompe ...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Probleme pour utiliser ma dll en release
    Par irnbru dans le forum MFC
    Réponses: 4
    Dernier message: 30/09/2007, 15h01
  2. Réponses: 1
    Dernier message: 30/06/2006, 15h49
  3. Création DLL pour utilisation sur VBA
    Par Fbartolo dans le forum C++Builder
    Réponses: 1
    Dernier message: 21/11/2005, 20h44
  4. [JNI] Difficultés pour utiliser une DLL
    Par etiennegaloup dans le forum Entrée/Sortie
    Réponses: 10
    Dernier message: 15/08/2005, 21h29
  5. [DLL] Utilisation d'une DLL pour utiliser serveur Firebird
    Par sekiryou dans le forum Bases de données
    Réponses: 2
    Dernier message: 11/08/2004, 14h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo