Déclaration + procédure dll C++

[Résolu]
Signaler
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007
-
Messages postés
7741
Date d'inscription
mercredi 1 septembre 2004
Statut
Membre
Dernière intervention
24 septembre 2014
-
J'ai une dll C++ avec les fonctions déclarées comme ceci :
Int EPGetDeviceID(HANDLE *PrnHandle, LPTSTR lpDeviceID
);

Args:

HANDLE       PrnHandle     [IN] Printer handle acquired with
EPOpenComm function

LPTSTR         lpDeviceID     [IN] Pointer to memory storing the DeviceID
information

                                               [OUT]
Acquired the DeviceID information

 

Returns SUCCESS (0) if successful.

Returns the following error codes in case of error

DEVICE_IO_ERROR (4) Error with low level communication

 

int EPWriteComm(HANDLE PrnHandle, LPCVOID pData, DWORD
dwDataLen);

// Write to printer port handle

 

Args:

HANDLE       PrnHandle     [IN] Printer handle acquired with OpenComm
function

LPCVOID      pData             [IN] Pointer to memory storing
datas to send

DWORD        dwDataLen    [IN] Length of storing buffer

 

Returns SUCCESS (0) if successful.

Returns the following error codes in case of error

ERROR_ON_WRITTING_PORT (5)                     A port writing error has occured

ERROR_ON_WRITTING_FUNCTION (6)            A writing error has occured

 

 

int EPReadComm(HANDLE PrnHandle, LPVOID pData, DWORD
*dwDataLen);

// Read from printer port handle

Args:

HANDLE       PrnHandle     [IN] Printer handle acquired with OpenComm
function

LPVOID         pData             [IN] Pointer to memory which will
store received datas

                                               [OUT]
Acquired datas

DWORD        *dwDataLen  [IN] Pointer to length of storing buffer

                                               [OUT]
Length of acquired datas

 

Returns SUCCESS (0) if successful.

Returns the following error codes in case of error

ERROR_ON_READING_FUNCTION (7)A read error has occured

LPCVOID et LPVOID, vous connaissez ?
Comment déclarer ceci dans un module et l'utiliser dans le Form ?
Merci bien de votre aide.

16 réponses

Messages postés
7741
Date d'inscription
mercredi 1 septembre 2004
Statut
Membre
Dernière intervention
24 septembre 2014
41
Private Type TDevID
    Mfg as string * 256
    Cmd as string * 256
    Mdl as string * 256
    Cls as string * 256
    Des as string * 256
End Type

Dim DeviceID as TDevType

Mfg, cmd, ... sont les membres de ta structure

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

Les exports semblant faits en pur style C, je pense que tu peus réduire les déclarations:
Public Declare Function WriteComm Lib "EPComDll.dll" Alias "[mailto:_EPWriteComm@12 _EPWriteComm@12]" (ByVal handle As Long, ByVal LPCData As String, ByVal dwDataLen As Long) As Long

=> Non, je ne peux, le source dll que je n'ai point à été fait en VC++ 6

Casy, apparement, je ne peux tout avoir :
   Mfg as string * 256
    Cmd as string * 256
    Mdl as string * 256
    Cls as string * 256
    Des as string * 256

J'ai fait : GetID = GetDeviceID(hprinter, ID)
                 Text1.Text = ID.Mfg
                 Text2.Text = ID.Cmd
             .....
mais je n'ai que Text1.Text qui affiche la chaine et tout d'un coup, séparer par des ;  -> MFG:xxxxxxx;CMD:xxxxxxxxx;.......
Bizarre !?
Par contre pour une autre fonction appelant une structure similaire, j'ai le détail !?

Sinon, pour :
Public Declare Function WriteComm Lib "EPComDll.dll" Alias
"_EPWriteComm@12" (ByVal handle As Long, ByVal LPCData As String, ByVal
dwDataLen As Long) As Long

Public Declare Function ReadComm Lib
"EPComDll.dll" Alias "_EPReadComm@12" (ByVal handle As Long, ByVal
LPData As String, ByRef dwDataLen As Long) As Long

C'est OK, mais As Integer à la fin suffit et As any à la place de As String marche aussi !
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
LPVOID : adresse mémoire
LPCVOID : idem, le C en plus indique qu'on ne fera QUE LIRE ce qui est à cette adresse.

ciao...
BruNews, MVP VC++
Messages postés
7741
Date d'inscription
mercredi 1 septembre 2004
Statut
Membre
Dernière intervention
24 septembre 2014
41
LP pour Long Pointeur et Void pour type indefinie. Cela signifie que tu passe un pointeur long (adresse absolu) sur une variable de type non définie
Cela veut dire que tu doit passer à ta fonction, l'adresse mémoire de ta variable.

Alors comme ici tes variables seront des chaines de caractères, les choses se compliquent un peu. Une chaine de caractère passée à une fonction est déjà une adresse mémoire. MAis suivant comment est déclaré en C la variable de réception, il faut passer la chaine soit par valeur (ByVal) soit par référence (ByRef). Il faut donc que tu fasse l'essai avec les 2 cas.

Par contre, il faut que ta chaine existe en mémoire avant l'appel de la fonction. Une simple déclaration ne suffit pas, il faut remplir la chaine pour qu'elle soit créer en mémoire. En général on fait chaine = String(255,chr(0)) juste avant l'appel. Ca crée une chaine de 255 caractères.

Je suis pas sur d'avoir été très clair dans mes explications.

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
On ne passe jamais une String VB par référence car ce serait l'adresse du BSTR et non la chaine (qui est un champ du BSTR). Il faudrait pour cela que la DLL ait été écrite spécialement pour VB.

ciao...
BruNews, MVP VC++
Messages postés
7741
Date d'inscription
mercredi 1 septembre 2004
Statut
Membre
Dernière intervention
24 septembre 2014
41
Si si, ça m'est arrivé BruNews, sur une Dll écrite pour du C que j'ai dû utiliser en VB, pour une fonction où c'était un pointeur sur une variable qui était attendu. Cette variable étant elle-même un pointeur sur la zone mémoire de la chaine de caractère. La déclaration était celle-ci : (LPSTR *chaine)

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
Messages postés
7741
Date d'inscription
mercredi 1 septembre 2004
Statut
Membre
Dernière intervention
24 septembre 2014
41
oups j'ai oublier la moitié de la phrase.
La déclaration était un (LPquelquechose chaine), et en fouillant dans les .h, j'ai réussi à trouvé qu'il correspondait à (LPSTR *chaine)

Déclaration perverse s'il peut en etre

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
LPSTR *chaine
demande l'adresse d'un TABLEAU de chaine mais pas d'une chaine.

ciao...
BruNews, MVP VC++
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

Faire chaine = String(255,chr(0)) ou Dim chaine * 255 au début, c'est la même chose non ?

Sinon voici comment j'ai déclaré dans un module :
Public Declare Function WriteComm Lib "EPComDll.dll" Alias "_EPWriteComm@12" (ByVal handle As Long, ByRef LPCData As Any, ByVal dwDataLen As Long) As Integer

Public Declare Function ReadComm Lib "EPComDll.dll" Alias "_EPReadComm@12" (ByVal handle As Long, ByRef LPData As Any, ByRef dwDataLen As Long) As Integer

Public Declare Function GetDeviceID Lib "EPComDll.dll" Alias "_EPGetDeviceID@8" (ByVal handle As Long, ByRef DeviceID As String) As Integer

(J'avais oublier de vous préciser GetPrnHandle dont je suis sûr)
Public Declare Function GetPrnHandle Lib "EPComDll.dll" Alias "_EPGetEPLPrnHandle@8" (ByVal port As Integer, ByRef handle As Long) As Integer

Ce que j'ai mis en rouge, c'est ce dont je ne suis certain à 100%...

Et dans le Form :
Dim hPrinter As Long

Function SetHandle() As Boolean
    SetHandle = GetPrnHandle(USBPort, hPrinter)
End Function
'Ce qui est au-dessus ne changera plus

Dime ID * 255
Dim GetID As Integer
If (ID = 0) Then
        GetID = GetDeviceID(hPrinter, ID)   'ici ça plante sans me donner d'erreur et ça ferme de suite VB Studio, je sais pas pourquoi ?
        Text14.Text = ID
Else:
        MsgBox "Error with low level communication" & vbCrLf & Err.Description
End If

Dim Data As String
Dim Send As Integer
Dim DataLen As Long

Dim Buffer As String * 30
Dim Receive As Integer
Dim nb As Long

Data$ = Chr(64) & Chr(69) & Chr(74) & Chr(76) & Chr(32) & Chr(73) & _
               Chr(81) & Chr(32) & Chr(85) & Chr(83) & Chr(66) & Chr(73) & Chr(68) & vbCrLf
               'c'est une commande que j'envoi à l'imprimante

DataLen = Len(Data)

For i = 1 To 100   'tempo au-hasard pour attendre la réception

    If Send = 0 Then
            Send = WriteComm(hPrinter, Data, DataLen)
    ElseIf (Send = 5) Then
            MsgBox "A port writting error has occured" & vbCrLf & Err.Description
    ElseIf (Send = 6) Then
            MsgBox "A writting error has occured" & vbCrLf & Err.Description
    End If

    Receive = ReadComm(hPrinter, Buffer, nb)   'il y a rien dans le buffer ?
    nb = Len(Buffer)
    Buffer = Left(hPrinter, Buffer, nb) 'Troncage du buffer sur le nombre de caractères   effectivement lus mais ça me met comme erreur

Next i
  
    Text1.Text = Data & Lineoftext & vbCrLf
    Text1.Enabled = True
   
    Text2.Text = Buffer & Lineoftext & vbCrLf
    Text2.Enabled = True
  

CloseComm (hPrinter)  'ferme le port USB ou LPT

End Sub

Voilou, merci encore pour votre aide précieuse
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
... Alias "[mailto:_EPGetDeviceID@8 _EPGetDeviceID@8]" (ByVal handle As Long, ByRef DeviceID As String)

j'ai expliqué plus haut pourquoi ByRef sur String VB ne peut pas aller.

ciao...
BruNews, MVP VC++
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

Buffer = Left(hPrinter, Buffer, nb) 
'Troncage du buffer sur le nombre de caractères   effectivement lus mais ça me met comme erreur








Désolé j'ai pas fini ma phrase :



ça me met comme erreur "Nombre d'arguments incorrect ou affectation de propriété incorrecte" (mais comm il ya rien dans le buffer, c'est peut-être normal ?
Messages postés
7741
Date d'inscription
mercredi 1 septembre 2004
Statut
Membre
Dernière intervention
24 septembre 2014
41
hPrinter doit etre le handle que tu as lu avec la fonction EPOpenComm, déjà il faut commencer par ça.

Ensuite regarde dans ta doc, mais pour moi DeviceID doit etre certainement une structure que tu dois passer à la fonction pour qu'elle la remplisse.

Pour les déclarations j'aurais plutot mis ça :

Public Declare Function WriteComm Lib "EPComDll.dll" Alias "_EPWriteComm@12" (ByVal handle As Long, ByVal LPCData As String, ByVal dwDataLen As Long) As Long

Public Declare Function ReadComm Lib "EPComDll.dll" Alias "_EPReadComm@12" (ByVal handle As Long, ByVal LPData As String, ByRef dwDataLen As Long) As Long

Public Declare Function GetDeviceID Lib "EPComDll.dll" Alias "_EPGetDeviceID@8" (ByRef handle As Long, ByVal DeviceID As TypeDeLaStructure) As Long

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

J'ai essayé avec ByVal aussi mais ça ne passe pas, ça me met "Erreur d'exécution type 13, Type incompatible".
Si ça ne marche peut-être pas, c'est qu'il faudra peut-être faire un Public Type.
J'ai trouvé ça dans le source C :
#define MAX_DEVICE_NAME    256

typedef struct _DEVICEID{
    char MFG[MAX_DEVICE_NAME];
    char CMD[MAX_DEVICE_NAME];
    char MDL[MAX_DEVICE_NAME];
    char CLS[MAX_DEVICE_NAME];
    char DES[MAX_DEVICE_NAME];
}DEVICEID, *LPDEVICEID;

Traduction en Visual Basic ?? Vous connaisser MFG, CMD... ?
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
Les exports semblant faits en pur style C, je pense que tu peus réduire les déclarations:
Public Declare Function WriteComm Lib "EPComDll.dll" Alias "[mailto:_EPWriteComm@12 _EPWriteComm@12]" (ByVal handle As Long, ByVal LPCData As String, ByVal dwDataLen As Long) As Long

en:
Public Declare Function EPWriteComm Lib "EPComDll.dll" (ByVal handle As Long, ByVal LPCData As String, ByVal dwDataLen As Long) As Long
VB devrait trouver les fonctions sans problème.

ciao...
BruNews, MVP VC++
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
"fait en VC++ 6" ne veut strictement rien dire, VC++ est un IDE et non un langage, on y écrit ASM, C ou C++.
Les noms de fonction exportées sont en pur export C stdcall (c'est une info, pas une question...), en C++ se reconnaitrait illico à la déco du nom et serait inutilisable par quelque autre langage.

ciao...
BruNews, MVP VC++
Messages postés
7741
Date d'inscription
mercredi 1 septembre 2004
Statut
Membre
Dernière intervention
24 septembre 2014
41
"...C'est OK, mais As Integer à la fin suffit..."

NON, un int en C correspond à un long en VB, il te faut donc mettre le bon type correspondant sinon tu prend le risque d'avoir des appels instables sources de plantages.

Pour DeviceID, ok, il semblerait que ce soit bien une chaine de carctère dans ce cas là et non pas une structure. Farfelue ta dll.

Tu dis que tu as une autre fonction avec DeviceID sous forme de structure là, vérifie bien que le paramètre en C est bien de type
LPTSTR lpDeviceID

si c'est le cas je comprend plus rien, le parametre ne peux pas etre à la fois structure et chaine de caractère

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #