mahojul
Messages postés27Date d'inscriptionlundi 26 janvier 2009StatutMembreDernière intervention 6 mars 2009
-
19 févr. 2009 à 06:21
mahojul
Messages postés27Date d'inscriptionlundi 26 janvier 2009StatutMembreDernière intervention 6 mars 2009
-
20 févr. 2009 à 09:27
Bonjour à tous,
Je développe un petit programme en VB6 basé sur un code en C++ qui va lire une valeur dans un périphérique connecté par USB.
Au niveau de la connexion avec le périphérique pas de soucis tout roule comme on dit ... Mais par contre je rencontre quelques soucis pour lire une valeur.
Ce que je dois faire pour lire une valeur c'est appeler la fonction "TP_PM249_GetCounter" qui se trouve dans une DLL (que je possède). Pour faire cela, en code C++ voici comment faire :
Et moi ce que je cherche à faire, c'est la même chose mais ... en VB6 ... et comme vous pouvez le voir dans le code C++ il faut faire appelle à des adresse mémoire de variable (&lCounter, &lStatus). Voici comment j'ai procédé :
1) Déclaration dans un module des fonctions suivantes : Public Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
Public Declare Function TP_PM249_GetCounter Lib "TP_PM249.dll" (ByVal dwDevice As Long, ByRef Count As Long, ByRef Status As Long) As Boolean
2) Code (positionné sur un TIMER du formulaire) : Dim ptr_LCounter As Long ' pointer value
Dim ptr_LStatus As Long ' pointer value
Dim lcounter As String
Dim lStatus As String
Lors de l'exécution du code en VB6, voici le contenu de :
ptr_LCounter ---> 1895948
ptr_LStatus ---> 2079476
(si j'exécute une seconde fois le code, les valeurs changent. Voici les valeurs que j'ai :
ptr_LCounter ---> 2079476
ptr_LStatus ---> 1595700)
Or, lorsque j'exécute le code en C++, voici le contenu de :
&lCounter --->0x0012f150
&lStatus ---> 0x0012f14C
(si j'exécute le code plusieurs fois, les valeurs ne changent pas).
Le but de tout ça c'est de pouvoir avoir en VB6 ce que je trouve en C++ c'est à dire les valeurs des adresses des variables ... afin que je puisse les passer en paramètre à la fonction : TP_PM249_GetCounter
Est-ce que vous pourriez m'aider un peu pour résoudre ce problème ? Je vous remercie d'avance pour le temps que vous allez consacrer à ce problème ...
mahojul
Messages postés27Date d'inscriptionlundi 26 janvier 2009StatutMembreDernière intervention 6 mars 2009 19 févr. 2009 à 09:06
Bonjour,
Merci pour ta réponse ...
Alors voici la transformation du code selon tes conseils :
1) Déclaration dans un module des fonctions suivantes : (AUCUNS CHANGEMENTS A CE NIVEAU LA)
Public Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
Public
Declare Function TP_PM249_GetCounter Lib "TP_PM249.dll" (ByVal dwDevice
As Long, ByRef Count As Long, ByRef Status As Long) As Boolean
2) Code (positionné sur un TIMER du formulaire) :
Dim lcounter As
Long
Dim lStatus As
Long
lcounter = 0
lStatus = 0
SI_STATUS = TP_PM249_GetCounter(DevNum - 1,
lcounter
,
lStatus
)
Lorsque j'exécute mon code, voici les valeurs de :
lcounter --> 0
lStatus --> 0
au moment du passage dans : "
SI_STATUS = TP_PM249_GetCounter(DevNum - 1,
lcounter
,
lStatus
)
"
Dans ma variable "SI_STATUS" j'ai "FALSE" ce qui signifie que cela n'a pas fonctionné ... ...
Afin de tout tester, j'ai tenter de mettre ce code là :
2) Code (positionné sur un TIMER du formulaire) :
Dim ptr_LCounter As Long ' pointer value
Dim ptr_LStatus As Long ' pointer value
Lorsque j'exécute mon code, voici les valeurs de :
ptr_LCounter--> 1309232
ptr_LStatus--> 1309828
au moment du passage dans : "
SI_STATUS = TP_PM249_GetCounter(DevNum - 1,
ptr_LCounter
,
ptr_LStatus
)
"
ce qui me semble déjà plus logique que ce que l'on avait avant ... ...
Lorsque l'on exécute ce code plusieurs fois, les valeurs de ptr_LCounter et ptr_LStatus sont toujours aux valeurs indiquées ci-dessus ce qui ressemble plus au fonctionnement que j'ai avec le code en C++ ... il me semble que l'on tient le bon bout mais j'ai encore des soucis ...
En C++ j'ai mis des points d'arrêt pour comprendre ce qui se passait dans le code ... voici mon annalyse :
Je souhaite y passer en paramètre : "la référence de mon périphériques USB", l'adresse mémoire de la variable lCounter, l'adresse mémoire de la variable lStatus dans le but que cette fonction me retourne comme contenu dans lCounter la valeur lue par mon périphérique USB. En C++, lors de l'interrogation de la fonction "
TP_PM249_GetCounter
" avec les paramètres cité, la variable lCounter prend la valeur lue ... or, en VB6, lCounter ne prend rien du tout ... on dirait qu'il n'y a même aucune liaison entre elles.
Renfield dit : là, tu donne un pointeur vers le pointeur de ta variable
--> (le Byref ajoute un niveau)
Mahojul dit :
un pointeur vers le pointeur ? ... c'est pas très bien ça ... non ? ... Donc en fait, le simple fait déjà de déclarer ma fonction comme suit :
Public Declare Function TP_PM249_GetCounter Lib "TP_PM249.dll" (ByVal dwDevice As Long, ByRef Count As Variant, ByRef Status As Variant) As Boolean
dit déjà qu'il faut prendre un pointeur car j'ai mis "
ByRef
" ... (c'est juste pour bien comprendre) ... Donc à la base, je ne devrais pas, par la suite, utiliser :
VarPtr
?
Renfield dit : testes-tu ton programme en débug ? ou as tu compilé ta dll et ton projet VB6
Mahojul dit :
Alors mon programme en VB6 je l'ai testé en "DEBUG". Concernant la DLL c'est une DLL que j'ai mise dans le dossier où est contenu mon projet VB6. Je n'ai rien fait de spécial avec cette DLL au niveau de VB6 mis à part l'appeler ...
Renfield dit : parce qu'il est possible d'accrocher VB6 a ton projet visual studio, en live
Mahojul dit :
Ok, alors ça je ne savais pas ... ... qu'est-ce que cela changerait dans mon cas si on faisait cet "ACCROCHAGE" ? ... Je ne connais absolument pas cette possibilité ...
Mahojul dit :
J'espère que je m'exprime correctement ... mais c'est vrai que j'ai un peu de mal avec tous ces termes car je débute un peu ... mais bon ... si on essai pas on apprend pas ... donc je persévère ....
Mahojul dit :
Merci beaucoup pour ton aide ...
Vous n’avez pas trouvé la réponse que vous recherchez ?
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202175 19 févr. 2009 à 09:36
mets pas de Variant, j'ai même un doute sur le Boolean (a voir la déclaration de la fonction exportée.)
tu as bien saisi pour la suite:
soit tu mets byval x as long
et tu transmets le VarPtr de ta variable
soit tu mets ByRef x as long
et VB transmettra l'adresse de la variable
mais si tu fais Byref x As long
et que tu transmets VarPtr, tu donne bien l'addresse d'une variable qui contient l'adresse de ta variable counter, au final...
accrocher Visual Basic a visual studio, et non a la dll compilée est que tu pourrais executer le tout en pas a pas, et suivre la chose au travers des deux environnements.
plus simple: compiler le VB6, une fois bien codé
et dans les parametres de on projet de dll, dire quand tu la lance, ca execute ton fichier exe compilé.
ainsi, VB en fera pas reference a la dll compilée, mais au projet.
(pas de changement de code VB a faire pour ca, c'est le GetModuleHandle de Windows qui redirige)
Donc pour la suite du code qui est l'affichage du calcul suivant : MsgBox RATIO * lcounter ben j'obtiens "0" ... en effet, lcounter a toujours sa valeur à 0 et la fonction
"
TP_PM249_GetCounter
"
me retourne "FALSE"
En résumé, ce n'est toujours pas ce que je veux ... ... ... Dans le code C, lorsque je l'exécute, après le passage dans la ligne suivante :
if (!TP_PM249_GetCounter(m_iAxe + 1, &lCounter, &lStatus))
lCounter prend une valeur ...
qui est attribué (je pense) par la fonction "
TP_PM249_GetCounter
". Pourquoi n'est-ce pas le cas en VB6 ? ...
C'est peut être moi qui ne comprend pas bien ce que tu as voulu m'expliquer ... c'est fort possible ... mais j'aimerais bien comprendre pourquoi en C cela fonctionne et pas en VB6 ... ...
mahojul
Messages postés27Date d'inscriptionlundi 26 janvier 2009StatutMembreDernière intervention 6 mars 2009 19 févr. 2009 à 10:48
Voici mon code complet en VB6 :
1) Déclaration : 'DLL --> SiUSBXp.dll
Public Declare Function SI_GetNumDevices Lib "SiUSBXp.dll" (ByRef lpwdNumDevices As Long) As Integer
Public Declare Function SI_SetTimeouts Lib "SiUSBXp.dll" (ByVal dwReadTimeout As Long, dwWriteTimeout As Long) As Integer
Public Declare Function SI_Open Lib "SiUSBXp.dll" (ByVal dwDevice As Long, ByRef cyHandle As Long) As Integer
'DLL --> TP_PM249.dll
Public Declare Function TP_PM249_Initialize Lib "TP_PM249.dll" (ByVal dwDevice As Long) As Integer
Public Declare Function TP_PM249_GetCounter Lib "TP_PM249.dll" (ByVal dwDevice As Long, ByRef lcounter As Long, ByRef lStatus As Long) As Boolean
Public Declare Function TP_PM249_SetMultiplier Lib "TP_PM249.dll" (ByVal dwDevice As Long, ByRef Multiplier As Long) As Integer
Public Declare Function TP_PM249_SetMode Lib "TP_PM249.dll" (ByVal dwDevice As Long, ByRef RefMode As Long) As Integer
2) Code sur "Timer"
Private Sub Timer1_Timer()
lcounter = 0
lStatus = 0
'On récupère les périphériques connectés (par rapport à la DLL SiUSBXp.dll
--> Dans notre cas cela ne nous concerne pas. )
SI_STATUS = SI_GetNumDevices(DevNum)
CtrlValeurStatut (SI_STATUS)
'On définit le timeout pour l'écriture et la lecture (par rapport à la DLL
SiUSBXp.dll
--> Dans notre cas cela ne nous concerne pas. )
SI_STATUS = SI_SetTimeouts(1000, 1000)
CtrlValeurStatut (SI_STATUS)
'On ouvre la connexion
'(DevNum - 1) = 0 --> Sélection du premier périphérique (par rapport à la DLL
SiUSBXp.dll
--> Dans notre cas cela ne nous concerne pas. )
SI_STATUS = SI_Open(DevNum - 1, hUSBDevice)
CtrlValeurStatut (SI_STATUS)
'Les 3 lignes ci-dessous fonctionne correctement ... à chaque passage, SI_STATUS vaut la valeur de réussite qui est " 0 "
SI_STATUS = TP_PM249_Initialize(DevNum - 1)
SI_STATUS = TP_PM249_SetMultiplier(DevNum - 1, 1)
SI_STATUS = TP_PM249_SetMode(DevNum - 1, PM249_NO_REF)
'LA LIGNE QUI POSE SOUCIS EST ICI :
SI_STATUS = TP_PM249_GetCounter(DevNum - 1, LCounter, LStatus)
MsgBox LCounter * Ratio
End Sub
Voili, cette fois tu as tout ce que j'ai fait ... à la fois le code VB6 ... et le code C ...
mahojul
Messages postés27Date d'inscriptionlundi 26 janvier 2009StatutMembreDernière intervention 6 mars 2009 19 févr. 2009 à 11:17
Alors :
Ces 4 variables sont déclarés dans mon modules de définition soit :
Pour lcounter -->
Global lcounter as long
Pour lStatus -->
Global lStatus as long
Pour DevNum -->
Global DevNum as long
Pour hUSBDevice -->
Global hUSBDevice as long
--> La variable est remplie lorsque le formulaire se charge. (voir code ci-dessous
Private Sub Form_Load()
)
Ces variables sont remplies lors de l'ouverture du formulaire grâce au code suivant :
Private Sub Form_Load()
'INVALID_HANDLE_VALUE est déclarée également dans le module de définition elle est déclarée comme suit : Public Const INVALID_HANDLE_VALUE = &H1
hUSBDevice = INVALID_HANDLE_VALUE
'Ici, on indique le numéro du périphérique connecté dans la variabl DevNum
CP210x_STATUS = CP210x_GetNumDevices(DevNum)
End Sub
La fonction
CP210x_GetNumDevices
est déclarée comme suit :
Public Declare Function CP210x_GetNumDevices Lib "CP210xManufacturing.dll" (ByRef lpwdNumDevices As Long) As Integer
mahojul
Messages postés27Date d'inscriptionlundi 26 janvier 2009StatutMembreDernière intervention 6 mars 2009 19 févr. 2009 à 12:07
J'ai suivi ton conseil,
J'ai mis : Option Explicit dans tous mes modules et j'ai fait CTRL + F5 pour débugger le code ... je n'ai pas eu de soucis ...
A la base je crois que Option Explicit fait que si on débug le code et qu'une variable n'est pas déclarée le code se met en erreur ... tant que la variable n'est pas déclarée ...
Pour ma part, aucunes erreurs ... tout est correctement déclaré ...
Que penses-tu de tout ça ... ?? ... on est pas très avancé ... ...
Je ne comprend vraiment pas la différence qu'il y a entre le C++ et mon code VB6 ...
Tout se joue sur cette ligne :
En C++ : --> if (!TP_PM249_GetCounter(m_iAxe + 1, &lCounter, &lStatus))
En VB6 : --> SI_STATUS = TP_PM249_GetCounter(devNum - 1, LCounter, LStatus)
Si on récapitule ... essayons de prendre les choses les unes après les autres ... ...
On est bien d'accord que au niveau de la déclaration on est juste ? ...
En C++ : --> TP_PM249_API bool __stdcall TP_PM249_GetCounter(long DeviceNo, long* Count, long* Status);
En VB6 : --> Public Declare Function TP_PM249_GetCounter Lib "TP_PM249.dll" (ByVal dwDevice As Long, ByRef lcounter As Long, ByRef lstatus As Long) As Boolean
long DeviceNo en C++ équivaut àByVal dwDevice As Long en VB6
long* Count en C++ équivaut à ByRef lcounter As Longen VB6
long* Status en C++ équivaut àByRef lstatus As Longen VB6
D'après mes recherches, le fait de déclarer qqch comme suit : long* Count en C++ dit que nous faisons référence à une adresse mémoire. En VB6 pour faire cela on utilise bien le "ByREF" donc à ce niveau pas de soucis normalement ... ...
Maintenant la question que je me pose est la suivante :
En mode débuggage du code C++, on voir bien que quand on passe à la ligne
if (!TP_PM249_GetCounter(m_iAxe + 1, &lCounter, &lStatus))
&Counter vaut une adresse mémoire --> 0x0012f150
&Status vaut également une adresse mémoire --> 0x0012f14c
(NOTE : Le fait de mettre un & devant le nom de la variable cela va donner son adresse mémoire en hexa selon mes recherches ... est-ce que en VB6 on pourrait faire la même chose ? )
Quand on arrive à la ligne suivante, lCounter vaut une valeur (-16) et lStatus vaut également une valeur (10)
En mode débuggage du code VB6, on voir bien que quand on passe à la ligne
SI_STATUS = TP_PM249_GetCounter(devNum - 1, LCounter, LStatus)
LCounter vaut --> 0
LStatus vaut --> 0
Quand on arrive à la ligne suivante, lCounter vaut TOUJOURS 0 et lStatus vaut également TOUJOURS 0
Est-ce que le problème ne viendrait pas de là ? ... ... J'ai voulu faire quelques esssais et j'ai essayer de passer en paramètre (pour le code VB6) directement une adresse mémoire et cela plante .... donc ce n'est pas ce qu'il faut faire ... ...
Est-ce que tu aurais une idée sur la chose ? ... Je bloque vraiment là ... ... ... J'essaie de faire des comparaisons du mieux que je peux pour essayer de trouver par moi même ... mais ... je bloque ... ... ... si cela se trouve c'est qqch de très évident ... mais qui ne nous saute pas aux yeux ... ...
mahojul
Messages postés27Date d'inscriptionlundi 26 janvier 2009StatutMembreDernière intervention 6 mars 2009 19 févr. 2009 à 13:11
Oui, c'est totalement normal ....
Au niveau du code C++, m_iAxe + 1(dans mon cas) 1 et en VB6 devNum - 1 aussi 1 ... donc sur ce point là ... pas de soucis .. ... ... tout roule ...
Voici le code VB6 :
Public Declare Function TP_PM249_Initialize Lib "TP_PM249.dll" (ByVal dwDevice As Long) As Integer
Public Declare Function TP_PM249_GetCounter Lib "TP_PM249.dll"
(ByVal dwDevice As Long, ByRef lcounter As Any, ByRef lstatus As Any)
As Boolean
Public Declare Function TP_PM249_ResetRef Lib "TP_PM249.dll" (ByVal dwDevice As Long) As Integer
Public Declare Function TP_PM249_SetMultiplier Lib "TP_PM249.dll"
(ByVal dwDevice As Long, ByVal Multiplier As Long) As Integer
Public Declare Function TP_PM249_SetMode Lib "TP_PM249.dll" (ByVal dwDevice As Long, ByVal RefMode As Long) As Integer
Public Declare Function TP_PM249_Version Lib "TP_PM249.dll" (ByVal dwDevice As Long, ByRef lpVersion As Long) As Integer
Public Declare Function TP_PM249_Close Lib "TP_PM249.dll" (ByVal dwDevice As Long) As Integer
Est-ce que tu vois ce que je veux dire ? ...
Une fois que j'ai changé le code VB6 comme suit :
Public Declare Function TP_PM249_Initialize Lib "TP_PM249.dll" (ByVal dwDevice As Long) As
Boolean
Public Declare Function TP_PM249_GetCounter Lib "TP_PM249.dll"
(ByVal dwDevice As Long, ByRef lcounter As Any, ByRef lstatus As Any)
As
Boolean
Public Declare Function TP_PM249_ResetRef Lib "TP_PM249.dll" (ByVal dwDevice As Long) As
Boolean
Public Declare Function TP_PM249_SetMultiplier Lib "TP_PM249.dll"
(ByVal dwDevice As Long, ByVal Multiplier As Long) As
Boolean
Public Declare Function TP_PM249_SetMode Lib "TP_PM249.dll" (ByVal dwDevice As Long, ByVal RefMode As Long) As
Boolean
Public Declare Function TP_PM249_Version Lib "TP_PM249.dll" (ByVal dwDevice As Long, ByRef lpVersion As Long) As
Boolean
Public Declare Function TP_PM249_Close Lib "TP_PM249.dll" (ByVal dwDevice As Long) As
Boolean
Voici ce que j'obtiens dans l'appel de mes fonctions : SI_STATUS TP_PM249_Initialize(devNum - 1) --> SI_STATUS FALSE
SI_STATUS = TP_PM249_SetMultiplier(devNum - 1, 1)
Donc ... par conséquent j'ai pensé à la chose suivante : Est-ce qu'il serait possible que ma DLL ne soit pas compatible avec VB6 ? ... ...
Pour mémoire voici le code présent dans le fichier ".h" de la DLL : // The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the TP_PM249_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// TP_PM249_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.