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

Windows Discussion :

Problème d'importation d'une DLL dans CVI


Sujet :

Windows

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 32
    Points : 13
    Points
    13
    Par défaut Problème d'importation d'une DLL dans CVI
    Bonjour,

    J'avais déjà posté il y a quelques temps un sujet sur la communication entre CVI et une DLL. Grâce à votre aide, j'étais parvenue à la conclusion qu'il me fallait le .lib de la DLL pour qu'elle puisse etre reconnue dans CVI.

    Maintenant que j'ai le .lib, je l'ai importé dans mon projet mais impossible d'utiliser la DLL, il me faudrait le header de la DLL, et comme je ne peux pas ouvrir la bibliothèque, je ne connais pas les prototypes des fonctions à mettre dans le header. Y a-t-il un moyen d'ouvrir la bibliothèque pour avoir les prototypes? Ou de créer le header à partir de la bibliothèque?

    J'étais persuadée d'avoir la solution et je me retrouve dans une impasse. Que faut-il faire pour utiliser une DLL non créée sous CVI dans un projet CVI?

    Merci d'avance

  2. #2
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Bizarre : si tu as la lib, tu dois aussi avoir les fichiers .h qui vont avec.
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 32
    Points : 13
    Points
    13
    Par défaut
    non justement, j'ai dû demander les .lib déjà, et là je ne pense pas pouvoir avoir les .h, autant demander le code source!! seule les DLL sont libres normalement.
    Il y a un fichier .pdf avec les prototypes des fonctions en VB, je vais essayer de traduire ça en C pour faire le .h mais je ne suis pas sure du tout d'y arriver, surtout quand je vois les types de variables utilisés ( string, bool...)pas toujours reconnus par C il me semble.
    Bref je vais devoir travailler avec un cours de C à coté de moi. Et là je dis : vive developpez.com!!!

    si quelqu'un a une solution plus rapide à me proposer je prends!!!

  4. #4
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Citation Envoyé par samanderson
    non justement, j'ai dû demander les .lib déjà, et là je ne pense pas pouvoir avoir les .h, autant demander le code source!! seule les DLL sont libres normalement.
    Non. Les fichiers en-tetes sont la pour definir l'interface proposee par la bibliotheque. Ils ne contiennent pas le code des fonctions. Ils sont necessaires pour l'utilisation de la bibliotheque et doivent etre fournis avec.

  5. #5
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Le .h est un fichier de déclarations, pas de définitions, il n'y a pas de code source dans les .h.
    Attention effectivement au type string en VB, tu aurais peut-être intérêt à traduire en C++.
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 32
    Points : 13
    Points
    13
    Par défaut
    ba, les fichiers d'en-tête n'étaient donnés, donc je doit faire sans.
    oui j'ai bien compris que dans le .h on ne met que les déclarations des fonctions, les fonction sont écrites dans la dll si je me souviens bien.
    Même en C++ les chaines ne sont pas reconnues je crois, non? et les booléens n'ont pas l'air d'être reconnus en C. Et à la fin je suis censée intégrer tout ça dans un projet déjà écrit en C.
    Et si dans la DLL les fonctions sont écrites en VB, ça ne risque pas de poser problème?

  7. #7
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Points : 1 067
    Points
    1 067
    Par défaut
    Citation Envoyé par samanderson
    Il y a un fichier .pdf avec les prototypes des fonctions en VB, je vais essayer de traduire ça en C pour faire le .h mais je ne suis pas sure du tout d'y arriver, surtout quand je vois les types de variables utilisés ( string, bool...)pas toujours reconnus par C il me semble.
    Les "prototypes" en question, ils commencent par "Declare" ?
    Tu pourrais peut-être nous mettre un ou deux exemples ici, non ? (j'ai prêté ma boule de cristal, désolé)
    Y a-t-il beaucoup de fonctions dans cette librairie ?
    Un problème bien exposé
    est, pour moitié, solutionné. / La connaissance s'accroît quand on la partage, pas quand on l'impose. / La violence est le langage des faibles.

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 32
    Points : 13
    Points
    13
    Par défaut
    J'ai les prototypes dans un tableau, voilà un exemple :
    "Function S_lambda_l (ByVal ref As String, ByVal T As Double, ByRef lam_l As Double) As Boolean"
    Plus loin j'ai des exemples de déclarations ainsi :
    "Declare Function S_lambda_l Lib "REF_CALC32.DLL" (ByVal ref As String, _
    ByVal T As Double, ByRef lam_l As Double) As Boolean"

    Si tu cherches à vérifier si c'est bien du VB, j'ai trouvé celà dans un dossier Visual Basic et le nom du pdf est " HelpVBE" E pour english. Je ne vois pas comment je pourrais me tromper là-dessus. Mais excuse moi quand même pour m'être mal expliquée et avoir oublié la phrase " j'espère n'avoir rien oublié et n'hésitez pas à me le dire si c'est le cas".
    Il y a 34 fonctions dans cette bibliothèque.

  9. #9
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Points : 1 067
    Points
    1 067
    Par défaut
    Citation Envoyé par samanderson
    J'ai les prototypes dans un tableau, voilà un exemple :
    "Function S_lambda_l (ByVal ref As String, ByVal T As Double, ByRef lam_l As Double) As Boolean"
    Plus loin j'ai des exemples de déclarations ainsi :
    "Declare Function S_lambda_l Lib "REF_CALC32.DLL" (ByVal ref As String, _
    ByVal T As Double, ByRef lam_l As Double) As Boolean"

    Si tu cherches à vérifier si c'est bien du VB, j'ai trouvé celà dans un dossier Visual Basic et le nom du pdf est " HelpVBE" E pour english. Je ne vois pas comment je pourrais me tromper là-dessus. Mais excuse moi quand même pour m'être mal expliquée et avoir oublié la phrase " j'espère n'avoir rien oublié et n'hésitez pas à me le dire si c'est le cas".
    Il y a 34 fonctions dans cette bibliothèque.
    Bonsoir,

    Désolé pour le temps de réponse mais...j'avais oublié ton message

    Si je te demandais un exemple de prototype, ce n'était pas pour vérifier que c'était du VB, mais pour voir si il y avait une chance que la DLL exporte des fonctions supportant les types de données utilisés par VB. Quand je dis "chance", il faut comprendre "probabilité", sinon je pensais plutôt à de la "malchance"...

    Ce qui pourrait être pas mal, c'est que tu choisisses la fonction la plus simple (peu de paramètres genre juste un Integer ou un Long, retournant un booléen) ou une fonction retournant une chaîne si il y en a une et que tu mettes le "Declare" correspondant ici (à moins qu'il y ait la doc. dans le setup dont tu as parlé dans l'autre thread).
    Ensuite, tu télécharges PEDump chez Microsoft et tu fais un "pedump.exe /A nomDeLaDll.dll > nomDeLaDll.dump.txt".
    Ensuite, cela donnera peut-être un résultat similaire (mais comme j'ai un doute à cette heure tardive), télécharges les binutils pour windows, décompresse l'archive et fais un "dlltool -z nomDeLaDll.def.txt --export-all-symbol nomDeLaDll.dll".
    Dans le ".dump.txt", il y a deux choses qui m'intéressent : la liste des imports et la description de la fonction exportée que tu as précédemment choisie.
    Dans le ".def.txt", tout m'intéresse sauf les lignes décrivant les fonctions autres que celle que tu as choisie.

    Dans le "Declare" que tu nous a donné, ce qui me fait peur, c'est le "Boolean" retourné. Il faut que je vérifie un truc mais en général quand une DLL en C retourne un BOOL, on déclare la fonction en VB comme retournant un "Long", pas un "Boolean".
    Donc je me dis que la DLL retourne peut-être un "Boolean" comme VB les connaît. Si c'est le cas, alors les chaînes de caractères attendues ne seront probablement pas des "char *" comme c'est le cas habituellement en C.
    Pour avoir une idée plus précise de la chose, la liste des imports de la DLL peuvent aider : si il y a de l'OLE dans le lot, c'est mauvais signe.

    En attendant que je refasse surface, tu peux jeter un oeil à http://rp.developpez.com/vb/tutoriels/dll/ bien que l'article ne soit pas aussi complet que je l'espérais (correspondances entre types VB et types C).

    J'espère que ce n'est pas urgent...envoie-moi un MP en fin de semaine si je semble avoir disparu pour que je me rappelle que j'ai commencé à répondre ici (le MP, c'est juste pour le rappel, pas pour poser d'autres questions techniques).

    Si je peux, je jetterai un oeil moi-même à cette DLL (c'est toujours la même que celle référencée dans ton précédent thread ?).

    Bonne nuit
    Un problème bien exposé
    est, pour moitié, solutionné. / La connaissance s'accroît quand on la partage, pas quand on l'impose. / La violence est le langage des faibles.

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 32
    Points : 13
    Points
    13
    Par défaut
    Voilà une des fonctions des plus simples :

    Declare Function S_molmas Lib "REF_CALC32.DLL" _
    (ByVal ref As String, ByRef mm As Double) As Boolean

    Toutes les fonctions retournent un booléen et prennent au moins un string et un double en paramètre.

    Avec pedump, j'ai une erreur d' "assertion failure". Je n'ai ni import, ni description de fonction dans le txt.
    Avec dlltool, j'ai : "REF_CALC32(nom de ma dll).dll : no symbols" sur la console. Dans le def.txt, j'ai seulement celà : "; dlltool -z REF_CALC32.def.txt --export-all-symbol REF_CALC32.dll
    EXPORTS"
    ce qui doit probablement s'enregistrer avant l'apparition de l'erreur.

    oui c'est toujours la même dll, téléchargée ici : http://www.solvay-fluor.com/news/res...000338,00.html
    Tu y trouveras aussi les .pdf, et les deux autres versions Delphi et Excel. Bref, tout ce que j'ai pour l'utiliser moins les librairies.

    Ce n'est pas vraiment urgent, mais ce serait bien si ça pouvait être fini fin aout.
    Merci beaucoup de m'aider à résoudre ce problème.

  11. #11
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Points : 1 067
    Points
    1 067
    Par défaut
    Bonsoir,

    Désolé d'avoir été un peu long, mais...il faut faire avec.

    Allons-y...

    Dans la documentation (de "Ref_Calc32") pour Delphi ("HelpDelE.pdf"), page 8, on peut lire :
    Syntax
    The following syntax applies for the import declaration:
    1. Import via name clause:
    Function S_Name(Refr:pChar [[;IPar_1][,IPar_2]:Double]; var RPar):
    WordBool;
    stdcall; external 'ref_calc32.dll'
    "stdcall" est la convention d'appel utilisée. Pour une DLL sous Windows, c'est la convention classique mais c'est important de le noter.
    On voit aussi que, d'après cette définition, toutes les fonctions :
    • retournent une valeur de type "WordBool" ;
    • reçoivent au moins un argument (et toujours le premier quand il y en a plus d'un) de type "pChar" ;
    • reçoivent toujours un argument par référence (cf. "var" avant son nom), situé en dernier, qui est vraisemblablement utilisé pour retourner une valeur [1] ;
    • reçoivent éventuellemnt un ou deux arguments de type "Double".

    Bref, très peu de types différents : cela sera plus simple.
    Note : une fonction déroge à ces règles : S_revision().

    Plus bas sur la même page, on peut lire :
    Parameter Types
    Following parameter types are compatible for data exchange between programmes and
    REF_CALC32.DLL (Delphi 2-4):
    • Zero terminated string: pChar
    • 8 Byte real: Double;
    • 2 Byte Boolean: WordBool (true und false) or
    Integertypes (e.g. Word, Integer; Werte: 0 und 1)
    The export type ”by reference” is enforced by using the key word ”var” The result of a
    calculation shall be exported ”by reference”.
    Les choses s'annoncent bien :)
    J'avais peur que les fonctions reçoivent des types tels que ceux utilisés par VB (comme des BSTR pour les chaînes par exemple [2])...mais non.
    Le type "pChar" correspond à un "char *" en C (cf. Pour plus d'informations sur les types de chaînes en Delphi).
    Le "Double" est un flottant sur 8 octets : comme le "double" en C (sous Windows sur x86) :)
    Le WordBool est un booléen sur 2 octets. Un "mot" ("word"), sur architecture Intel/32bits sous Windows (la terminologie peut être différente ailleurs) est un entier sur 2 octets. Quand on programme en C sous Windows, on peut utiliser (après inclusion de <windows.h>) un type appelé "WORD". Comme je ne sais pas si tu auras accès à ce type, j'utiliserai l'équivalent en C classique (toujours sous Windows sur x86/32bits) : "unsigned short".

    Donc, on a :
    • la convention d'appel ;
    • une idée de la "tête" des fonctions ;
    • la liste des types utilisés et leur correspondance en C.


    Il nous reste une petite chose à voir avant de pouvoir écrire un fichier d'entête : le passage de paramètre par référence.
    En C, tous les paramètres sont passés par valeur. Quand on souhaite qu'une fonction puisse modifier une variable, on lui transmet un pointeur sur cette dernière (ce qui explique que tous les paramètres soient passés par valeur : c'est bien la valeur du pointeur qu'on transmet).

    Prenons l'exemple de deux fonctions dont on va transformer la déclaration en Delphi (faite dans le fichier "ImportD.pas") en C :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Function S_revision (var version: pChar) : WordBool;
                        stdcall; external 'ref_calc32.dll';
    [...]
    Function S_p_b      (ref: pChar ; T:    double; var p: double ): WordBool;
                        stdcall; external 'ref_calc32.dll';
    Dans notre ".h" on mettra :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    extern __stdcall unsigned short S_revision(char *version);
    
    extern __stdcall unsigned short S_p_b(char *ref, double T, double *p);
    "extern" car ce sont des fonctions externes à notre programme et "__stdcall" pour spécifier la convention d'appel (par défaut, c'est "cdecl" en C).
    Le "pChar" placé en premier est, comme dit plus haut devenu un "char *".
    Le deuxième argument de "S_p_b()", un "double", est "devenu" un "double".
    La valeur retounée par les fonctions sera toujours de type "unsigned short".
    Le "double" passsé par référence ("var p: double"), devient un pointeur sur un double ("double *p").

    Ok ?

    Maintenant, il nous faut tester si cela fonctionne.
    Pour que notre programme de test (en C) puisse utiliser la DLL, nous avons deux solutions :
    • soit il charge la DLL dynamiquement (en appelant "LoadLibrary()") puis obtient l'adresse de la fonction à appeler (avec "GetProcAddress()") ;
    • soit, après la compilation (qui donne un fichier objet), on le lie avec une bibliothèque d'importation pour que la DLL soit chargée au démarage du programme par le "loader" de Windows.

    La deuxième solution est celle qui semble correspondre à ce qui est décrit dans http://perso.orange.fr/philippe.bauc...n projet CVI") cité dans ton précédent "thread" sur CVI, c'est donc celle que je vais utiliser.

    Donc, maintenant, nous avons besoin d'une bibliothèque d'importation.
    PEDump et dlltool ont échoué dans leur tâche, mais ce n'est pas grave : la documentation (et d'autres outils) nous donne la liste des fonctions exportées par la DLL...et c'est tout ce dont nous avons besoin pour créer une bibliothèque d'importation :)
    Créons le fichier "ref_calc32.a.def" contenant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    LIBRARY Ref_Calc32.dll
    EXPORTS
    S_revision@4
    S_p_b@16
    S_molmas@8
    S_p_d@16
    S_h_l@16
    S_h_v@24
    Note : j'ai mis plus de fonctions pour le programme de test qu'on verra après.
    Dans ce fichier, la première ligne indique le nom de la DLL.
    La seconde dit que ce qui suit est exporté par cette DLL.
    Les lignes suivantes décrivent les fonctions exportées. Leur format est "<nomFonction>@<sommeDeLaTailleDesArgumentsDeLaFonction>".
    Pour avoir la taille d'un argument, en se limitant aux seuls types utilisés dans le cas qui nous occupe, il suffit d'appliquer les règles suivantes :
    • les pointeurs ("char *" et "double *") ont une taille de 4 octets ;
    • les "double" ont une taille de 8 octets.

    Exemples :
    • la fonction "S_molmas()" attend un "char *" et modifie un "double" (donc attend un "double *"), ce qui fait 4 + 4 = 8 ;
    • la fonction "S_h_v()" attend un "char *", deux "double" et un "double *", ce qui fait 4 + (2*8) + 4 = 24.

    C'est bon ?

    Pour compiler mon programme de test, j'utiliserai gcc (Mingw32) donc je créerai la librairie d'importation en faisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dlltool -k -d ref_calc32.a.def -l libref_calc32.a
    Pour plus d'informations sur dlltool et la création de bibliothèques d'importation pour gcc, voir http://www.developpez.com/c/gcc/c800.html.


    Dans ton cas, vu que tu dois apparemment utiliser le format utilisé par MS VC++, il faudra utiliser un autre outil : "lib.exe".
    En théorie (je n'ai pas testé avec MSVC et je n'ai pas trouvé de moyen d'en générer un qui fonctionne aussi avec gcc), le fichier ".def" (que j'ai appelé "ref_calc32.lib.def") devrait dans ce cas se limiter à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    LIBRARY Ref_Calc32.dll
    EXPORTS
    S_revision
    S_p_b
    S_molmas
    S_p_d
    S_h_l
    S_h_v
    "lib.exe" devrait être inclus dans le .Net SDK mais je n'ai pas vérifié. J'ai généré un ".lib" avec la version de "lib.exe" livré avec MASM32 (moins gros à télécharger [3]) en faisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lib.exe /MACHINE:IX86 /DEF:ref_calc32.lib.def /OUT:ref_calc32.lib
    .


    Un outil (non testé) qui utilise dumpbin.exe et lib.exe pour créer une librairie d'importation à partir d'une DLL : ImpLib32.
    Une très bonne page concernant les outils permettant de générer des librairies d'importation : "Stdcall and DLL tools of MSVC and MinGW".
    Sur le même site, on peut trouver pexports, un outil permettant de générer un fichier DEF à partir d'une DLL.
    Note : comme dlltool et pedump, il plante avec ref_calc32.dll (en affichant quand même les exports). La DLL doit avoir un problème.


    Ecrivons maintenant un petit programme de test pour vérifier que cela fonctionne :
    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
    #include <stdio.h> /* pour printf() / fprintf() / etc */
    #include <stdlib.h> /* pour exit() / EXIT_SUCCESS / EXIT_FAILURE */
    #include "ref_calc32.h" /* notre fichier d'entête */
    
    #define TAILLE_CHAINE_REVISION 512
    
    #define REF "R407C"
    
    #define TEMP1 50.0
    #define TEMP2 273.15
    
    #define PRTDBL(__x__) printf(#__x__ " = %f\n",(__x__))
    #define PRTERR(__x__) fprintf(stderr,"Erreur lors de l'appel à S_" __x__ "()\n")
    
    int main(int argc, char *argv[])
    {
    	char revision[TAILLE_CHAINE_REVISION];
    	double pB, pD, hB, hD;
    	
    	if (S_revision(revision)) {
    		PRTERR("S_revision()");
    		exit(EXIT_FAILURE);
    	}
    	
    	printf("Version : '%s'\n",revision);
    
    	if (S_p_b(REF, TEMP1 + TEMP2, &pB)) {
    		PRTERR("p_b");
    		exit(EXIT_FAILURE);
    	}
    	PRTDBL(pB);
    
    	if (S_p_d(REF, TEMP1 + TEMP2, &pD)) {
    		PRTERR("p_d");
    		exit(EXIT_FAILURE);
    	}
    	PRTDBL(pD);
    
    	if (S_h_l(REF, TEMP1 + TEMP2, &hB)) {
    		PRTERR("h_l");
    		exit(EXIT_FAILURE);
    	}
    	PRTDBL(hB);
    
    	if (S_h_v(REF, TEMP1 + TEMP2, pD, &hD)) {
    		PRTERR("h_v");
    		exit(EXIT_FAILURE);
    	}
    	PRTDBL(hD);
    
    
    	exit(EXIT_SUCCESS);
    }
    Cet exemple se base sur celui présenté en page 9 de la documentation Delphi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if S_p_B('R407C', T + 273.15, pB) then EMessage;{bubble point pres. pB in Pa}
    if S_p_D('R407C', T + 273.15, pD) then EMessage; {dew point pres. pD in Pa}
    if S_h_L('R407C', T + 273.15, hB) then EMessage; {enthalpy,liq. hB in J/kg}
    if S_h_v('R407C', T + 273.15, pD, hD) then EMessage;
    {enthalpy ,sat. vapour: hD=f(T,pD) in J/kg}
    ...
    {Output of results T, pB, pD, hB, hD}
    ...
    end;
    ...
    Result:
    T [°C] pB [Pa] pD [Pa] hB [J/kg] hD [J/kg]
    50 2210451,3 1984604,2 276328,4 425604,5
    J'ai repris cet exemple pour pouvoir comparer les valeurs obtenues par notre programme de test avec quelque-chose de connu.

    Bien sûr, j'ai entre-temps complété mon fichier ".h" :
    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
    /*
     * Déclaration (partielle) des fonctions présentes dans la DLL REF_CALC32.DLL
     */
    
    extern __stdcall unsigned short S_revision(char *version);
    
    extern __stdcall unsigned short S_p_b(char *ref, double T, double *p);
    
    extern __stdcall unsigned short S_molmas(char *ref, double *mm);
    
    extern __stdcall unsigned short S_p_d(char *ref, double T, double *p);
    
    extern __stdcall unsigned short S_h_l(char *ref, double T, double *h_L);
    
    extern __stdcall unsigned short S_h_v(char *ref, double T, double p, double *h_v);
    Note : la fonction "S_molmas()" n'est pas utile pour l'exemple.


    Après compilation, je lance le programme de test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    E:\SOLVAY~1\Ref_Calc\Delphi\tests>test
    Version : '∟Ð6'
    pB = 2215920.581473
    pD = 1987774.739636
    hB = 276928.082425
    hD = 425917.045801
    On a un problème d'affichage de la version...mais sincèrement, la version...
    Pour le reste, les valeurs sont différentes, mais proches de ce qui était attendu : je serai tenté de conclure que cela fonctionne mais que leur documentation n'est pas à jour ou alors que mes "double" n'ont pas été initialisés comme ils l'auraient été en Delphi (?)... A toi de confirmer/infirmer.


    Voilà.
    On a fait le tour, là, non ?

    Ce qui te reste à faire :
    • compléter le ".h" avec les fonctions manquantes ;
    • compléter le ".def" si tu veux générer un ".lib" toi-même (a priori inutile si ils t'ont transmis le leur) ;
    • tester :)


    Des questions ?

    A+
    DS.



    PS : si cela résoud ton problème, penser au bouton "Résolu" (et tu me dois un verre) ; si tu penses que cela le vaut, une bonne note ne ferait pas de mal ( :) ) ; si quelqu'un pouvait tester le ".lib" avec MSVC, ça serait sympa ; les fichiers créés sont en PJ.
    PS2 :
    Citation Envoyé par samanderson
    mais ce serait bien si ça pouvait être fini fin aout.
    Ca, c'est mal.

    [1] - "vraisemblablement" à ce stade des observations, mais en fait c'est plus que vraisemblable : c'est dit dans la documentation.
    [2] - J'ai eu peur aussi en regardant quelles fonctions la DLL importait...En particulier (depuis oleaut32.dll) SysStringLen, SysFreeString, SysReAllocStringLen, SysAllocStringLen, VariantClear, VariantCopyInd et VariantChangeTypeEx : des fonctions utilisées pour manipuler les types de données de VB(A) (d'où ma question, dans un message précédent, sur les fonctions importées et la présence de "OLE" quelque part) !
    [3] - l'installation peut prendre un peu de temps par contre : quand une fenêtre style DOS s'affiche et qu'un message t'invite à appuyer sur une touche pour compiler les bibliothèques, tu peux essayer (non testé !) de la fermer sans appuyer sur une touche pour éviter cette étape si tu n'as pas l'intention d'utiliser MASM ("lib.exe" est décompressé avant d'en arriver là).
    Fichiers attachés Fichiers attachés
    Un problème bien exposé
    est, pour moitié, solutionné. / La connaissance s'accroît quand on la partage, pas quand on l'impose. / La violence est le langage des faibles.

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 32
    Points : 13
    Points
    13
    Par défaut
    Merci beaucoup de t'être penché sur mon problème.

    J'ai modifié mon fichier "ref_calc32.h" comme tu l'as fait, mais Labwindows n'a pas accepté la syntaxe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    extern __stdcall unsigned short S_revision(char *ref)
    J'ai donc modifié en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned short __stdcall S_revision(char *ref)
    et là il n'y a plus d'erreur dans le .h. Mais il y en a dans le code de mon programme.

    J'ai donc vérifié avec ton programme de test si j'avais le même résultat, et non je n'ai pas de résultat du tout sinon ces 5 lignes d'erreurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    5 Project link errors
       Undefined symbol '_S_revision@4' referenced in "T2.c".
       Undefined symbol '_S_p_b@16' referenced in "T2.c".
       Undefined symbol '_S_p_d@16' referenced in "T2.c".
       Undefined symbol '_S_h_l@16' referenced in "T2.c".
       Undefined symbol '_S_h_v@24' referenced in "T2.c".
    Je me demande sérieusement si la DLL est vraiment utilisable ou pas. J'ai pourtant bien inclut la DLL, la librairie et le .h au projet (qui s'appelle T2). Je ne comprends pas pourquoi ça ne marche toujours pas.

  13. #13
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Points : 1 067
    Points
    1 067
    Par défaut
    Bonjour,

    Citation Envoyé par samanderson
    [...] il n'y a plus d'erreur dans le .h. Mais il y en a dans le code de mon programme. [...]
    C'est à dire ? Quelles erreurs ? Quels messages d'erreur ? Sans précision, point de solution.

    Citation Envoyé par samanderson
    J'ai donc vérifié avec ton programme de test si j'avais le même résultat, et non je n'ai pas de résultat du tout sinon ces 5 lignes d'erreurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    5 Project link errors
       Undefined symbol '_S_revision@4' referenced in "T2.c".
       Undefined symbol '_S_p_b@16' referenced in "T2.c".
       Undefined symbol '_S_p_d@16' referenced in "T2.c".
       Undefined symbol '_S_h_l@16' referenced in "T2.c".
       Undefined symbol '_S_h_v@24' referenced in "T2.c".
    Ces 5 lignes sont produites par l'éditeur de liens (cf. "link errors").
    Le compilateur voit qu'une fonction S_p_b() est appelée, qu'elle doit recevoir des paramètres dont la taille totale est de 16 octets et qu'elle (le corps de la fonction, son code) n'est pas définie dans ton source : dans le fichier objet qu'il produit, il écrit alors que la fonction "_S_p_b@16" est utilisée. Il a repris le nom de la fonction et l'a "décoré" avec un "_" au début et "@16" à la fin.
    L'éditeur de lien voit ça et cherche cette fonction dans les éventuels autres fichiers objet et librairies qu'on lui dit d'utiliser. Comme il ne les trouve pas, il se plaint que le symbole "_S_p_b@16" n'est pas définit.
    Conclusion : la librairie utilisée ne contient pas le symbole "_S_p_b@16". Elle contient probablement "S_p_b@16" et/ou (plus probablement) "S_p_b".

    Citation Envoyé par samanderson
    Je me demande sérieusement si la DLL est vraiment utilisable ou pas.
    Elle l'est. Mon programme l'utilise, donc elle est utilisable.

    Citation Envoyé par samanderson
    J'ai pourtant bien inclut la DLL, la librairie [...]
    Tu dis "la librairie"... Laquelle exactement ? Celle qui t'a été fournie par Solvay ? Une que tu as créée en utilisant "lib.exe" comme proposé dans mon précédent message ? Rappel : sans précision, point de solution.

    En attendant, essaye ça (sans ajouter ni ".lib" ni ".dll" au projet) :
    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
    #include <windows.h> 
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NOM_DLL "ref_calc32.dll" /* nom (et éventuellement chemin) de la DLL à charger */
    #define NOM_FONCTION_SPB "S_p_b" /* nom de fonction tel qu'exporté par la DLL */
    
    #define REF "R407C" /* référence du "produit" pour lequel on fait les calculs */
    
    /* températures utilisées pour les "calculs" */
    #define TEMP1 50.0
    #define TEMP2 273.15
    
    /* Macros pour affichage d'erreur et de valeur de double */
    #define PRTDBL(__x__) printf(#__x__ " = %f\n",(__x__))
    #define PRTERR(__x__) fprintf(stderr,"ERREUR: %s\n",(__x__))
    
    /*
     * Définitions des types "pointeur de fonction" utilisés.
     * Pour chaque paramètre, un couple de lettres :
     * - "I" ou "O" pour indiquer si le parametre est en entrée ("In") ou en sortie ("Out") ;
     * - "S" pour un "char *", "D" pour un double, etc.
     * La méthode de nommage choisie est tout à fait subjective. Le but est de faire abstraction des noms de fonctions
     * et de ne déclarer les types qu'en fonction des paramètres attendus. Comme plusieurs fonctions attendent les mêmes
     * types de données comme paramètres, on pourra utiliser les mêmes types de pointeurs pour plusieurs d'entre elles.
     */
    /* Une "chaîne" (un "char *") en entrée, un "double" en entrée, un "double" en sortie  */
    typedef WORD __stdcall (*PFCT_ISIDOD)(char *ref, double T, double *p);
    
    int main(VOID)
    {
        HMODULE handleDLL; /* Handle de la DLL chargée */
        PFCT_ISIDOD S_p_b; /* pointeur vers la fonction S_p_b() de la DLL */
        WORD echecAppelFonction; /* "booléen" renvoyé par S_p_b() (ou par une autre fonction) */
        double pB; /* double "renvoyé" par S_p_b() */
        int valeurRetourMain=EXIT_FAILURE; /* valeur de retour de la fonction main(), échec par défaut */
    
        /* chargement de la DLL */
        handleDLL = LoadLibrary(NOMDLL);
        if (NULL == handleDLL) {
            PRTERR("echec chargement DLL");
            goto exit_main;
        }
    
        /* récupération de l'adresse de la fonction fonction S_p_b() */
        S_p_b=(PFCT_ISIDOD)GetProcAddress(handleDLL,NOM_FONCTION_SPB);
        if (NULL == S_p_b) {
            PRTERR("echec obtention adresse fonction");
            goto exit_fl_main;
        }
    
        /* appel de la fonction S_p_b() */
        echecAppelFonction=S_p_b(REF, TEMP1 + TEMP2, &pB);
        if ( echecAppelFonction ) {
            PRTERR("echec appel fonction");
            goto exit_fl_main;
        }
    
        /* affichage du résultat */
        PRTDBL(pB);
    
        /* si on arrive ici, c'est un succès */
        valeurRetourMain=EXIT_SUCCESS;
    
    exit_fl_main:
        FreeLibrary(handleDLL);
    exit_main:
        exit(valeurRetourMain);
    }
    Cordialement,
    DS.

    PS : je crois que je me suis trompé de fichier en en joignant un avec mon derneir message, désolé (mais rien de grave : tu n'as même pas essayé de le télécharger).
    Un problème bien exposé
    est, pour moitié, solutionné. / La connaissance s'accroît quand on la partage, pas quand on l'impose. / La violence est le langage des faibles.

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 32
    Points : 13
    Points
    13
    Par défaut
    Bonjour,

    Dans mon programme je n'arrive pas à utiliser le paramètre d'entrée sortie. Mais ce n'est pas le plus important, ça c'est parce que je débute en C.

    Je n'avais fait le test précédent qu'avec la librairie que m'avait fourni Solvay, j'ai retesté en créant une librairie avec lib.exe ( de MASM32), j'ai les même erreurs de liens.
    Je n'arrive pas à créer de librairie avec Implib32.

    J'ai aussi utilisé le dernier test, je n'ai pas eu d'erreur, j'ignore s'il y a eu affichage d'un résultat, la console s'est refermée dès la fin de l'execution et j'ignore (encore) comment lui dire de rester affichée.

    Merci encore
    Sam

  15. #15
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Points : 1 067
    Points
    1 067
    Par défaut
    Bonjour,

    Si tu as pû le compiler, alors je crois que tu vas te passer de ".lib".

    Citation Envoyé par samanderson
    la console s'est refermée dès la fin de l'execution et j'ignore (encore) comment lui dire de rester affichée.
    Essaye en remplaçant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    exit_main:
        exit(valeurRetourMain);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    exit_main:
        system(pause);
        exit(valeurRetourMain);
    Et dis moi ce que cela donne.
    Autre option : ouvrir un fichier en écriture au début du programme et écrire dedans au lieu d'utiliser "stderr".

    Cordialement,
    DS.
    Un problème bien exposé
    est, pour moitié, solutionné. / La connaissance s'accroît quand on la partage, pas quand on l'impose. / La violence est le langage des faibles.

  16. #16
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 32
    Points : 13
    Points
    13
    Par défaut
    Comme je n'arrivais pas à utiliser
    parce qu'il renvoyait la valeur "-3", j'ai triché en utilisant un scanf() et j'obtiens
    Si je n'ai pas besoin de .lib, ça veut dire que je me contente du header et de la dll? Je ne pensais pas qu'une dll pouvait se passer de son .lib.

  17. #17
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Points : 1 067
    Points
    1 067
    Par défaut
    Citation Envoyé par samanderson
    [...] j'obtiens
    Donc tu obtiens la même chose que moi : cela fonctionne (mis à part, comme déjà dit, que la valeur diffère de ce qui est indiqué dans la doc).

    Citation Envoyé par samanderson
    Si je n'ai pas besoin de .lib, ça veut dire que je me contente du header et de la dll? Je ne pensais pas qu'une dll pouvait se passer de son .lib.
    Une DLL peut être chargée implicitement ou explicitement.
    Implicitement, les informations concernant les DLL à charger et les fonctions de ces DLL à importer sont inscrites dans l'exécutable et c'est le chargeur de Windows qui s'occupe de charger la DLL au lancement du programme. Pour que les infos soient écrites dans l'exécutable, il faut un bibliothèque statique d'importation (le ".lib").
    Explicitement, c'est le programme qui appelle les fonctions nécessaires pour charger la DLL et récupérer les adresses des fonctions. Là, pas besoin de fichier ".lib".
    Plus d'infos (et une "engueulade") ce soir.
    En attendant, tu peux commencer à écrire les "typedef" qui correspondent aux autres fonctions.
    Un problème bien exposé
    est, pour moitié, solutionné. / La connaissance s'accroît quand on la partage, pas quand on l'impose. / La violence est le langage des faibles.

Discussions similaires

  1. [Débutant] Problème avec importation d'une dll
    Par Anonyme5571 dans le forum VB.NET
    Réponses: 7
    Dernier message: 03/10/2014, 09h29
  2. [Débutant] Problème d'import d'une dll VB6 dans un projet Visual Basic 2010
    Par kurt225 dans le forum VB.NET
    Réponses: 12
    Dernier message: 19/02/2014, 18h35
  3. Problème pour importer une dll dans un projet
    Par Kayl86 dans le forum VB.NET
    Réponses: 6
    Dernier message: 12/04/2010, 15h10
  4. Problème avec une DLL dans une boucle For
    Par BraDim dans le forum Langage
    Réponses: 5
    Dernier message: 20/09/2005, 12h22
  5. importation d'un fonction d'une dll dans mon application
    Par jeannot27 dans le forum C++Builder
    Réponses: 7
    Dernier message: 11/07/2005, 15h35

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