Polack77
Messages postés1098Date d'inscriptionmercredi 22 mars 2006StatutMembreDernière intervention22 octobre 2019
-
25 sept. 2007 à 17:40
Polack77
Messages postés1098Date d'inscriptionmercredi 22 mars 2006StatutMembreDernière intervention22 octobre 2019
-
27 sept. 2007 à 12:09
Bonjour
Historique (sans réel intérêt mais si ça vous intéresse voila) :
Je fais actuellement une classe (enfin 2, 1 VB6 et 1 VB.NET) qui dois me permettre
d'intégrer dans un application VB6 des forms VB.NET (Hé dit comme ça elle à la
classe ma classe, lol). Pour cela j'ai mit en place une classe intégrant des
WinSock (trouvé dans le fichier "mswsock.dll" dans "Windows\System32").
Mon appli VB6 démarre par shell l'appli VB.NET en lui indiquant en paramètre le
port à utilisé pour le WinSock. Grasse à ce dernier le handle de la form VB.NET
est retourné à VB6 qui intègre dans un shape la forme VB.NET correspondante (avec
les API). Sauf que, plusieurs mégas octets vont passé de VB6 à VB.NET et
inversement. Mes tests semble monté que le WinSock est un peut lent pour ce
genre de transfert. Je veut donc transmettre une adresse mémoire (par winsock)
à lire (par VB6 ou VB.NET suivant le cas). Vue que VB6 ne connais pas les
pointeur je veut une DLL qui retourne un long contenant l'adresse de la
variable que je lui passe (jusque là tout semble relativement simple). Je précise
que je n'ais jamais fait de DLL (j'en utilise tout le temps mais je ne les faits
pas). Comme ça vous savez pour cois je veut faire un 'truc' aussi con.
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
Objectif :
Je veut une DLL qui me retourne l’adresse mémoire d’une
variable que je lui passe, ce quel que soit sa taille ou son type.
Mon code :
VB
<hr align="center" size="2" width="100%" />
Private
Declare Function GetAdresse Lib "C:\Documents and
Settings\Vincent\Bureau\test.dll" (ByRef Variable As Any) As Long
Private Sub Form_Load()
Dim TESTE As String
TESTE = "Je fait des tests"
MsgBox TESTE & " " & GetAdresse(TESTE)
End Sub
<hr align="center" size="2" width="100%" />
C
(dans le .cpp)
<hr align="center" size="2" width="100%" />
#include
<windows.h>
long GetAdresse(void* Variable)
{
return (long)Variable;
}
<hr align="center" size="2" width="100%" />
C (dans le .def)
<hr align="center" size="2" width="100%" />
LIBRARY
test
EXPORTS
GetAdresse @1
<hr align="center" size="2" width="100%" />
Voila et dans VB à la ligne "MsgBox TESTE & " " &
GetAdresse(TESTE)" le compilo me retourne l'erreur : "Run-time error
'49': Bad DLL calling convention". Depuis midi je cherche à faire marche
cette $£¤µ* de DLL et ce que je trouve sois ne veut rien dire, sois je ne
comprend rien, sois ... bà je suis co_
Au faite à cois sers "@1" dans le .def?
Si non pourriez vous m'indiquer un tuto claire sur les DLL car je m'énerve
de plus en plus avec ce $£¤%µ de truc (qui me parais d’un niveau moins que
débutant)!!!
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 25 sept. 2007 à 19:29
Il te faut veuillez à ce que les fonctions exportées de ta dll soient exportées selon la convention _stdcall. Par défaut c'est la convention CDecl qui est utilisée et VB ne sais as référencer ce genre de fonction.
Ensuite il faut veiller aussi aux types de variables qui ne sont pas les même entre VB et C
Pour les tutos, tu peux peut-etre te référer à ce document :
Polack77
Messages postés1098Date d'inscriptionmercredi 22 mars 2006StatutMembreDernière intervention22 octobre 20191 27 sept. 2007 à 10:25
Je n'aime pas ne pas comprendre le pourquoi (surtout quand ça marche pas). Je cherche, je
trouve, et là... la frustration s'empare de moi :
Ma fonction fonctionnais depuis longtemps!!! En faite le problème été une faute
D'Inattention ( et ça me gonfle
de faire encor ce genre d'erreur à la co_).
Remarque : Deux petites modif quand même dans cette fonction :
Le deuxième paramètre reçu (LngEnOct) est maintenant en long et non plus en int. Le test du 'While' et maintenant "LngEnOct > 0" et non plus "LngEnOct != 0".
Cette fonction fonctionne (déjà posté le 26/09/2007 à 12:51:53 sans les deux modif ci-dessus)
<hr align="center" size="2" width="100%" />
void __stdcall SetVar(long
AdrsALire, long LngEnOct, void* VariableARemplire)
Mon problème se situais au niveau de la déclaration VB!!! Je déclarais
cette fonction comme fonction or il faut la déclarer en SUB étant donné qu'elle
ne retourne pas de valeur!!!
Ma déclaration qui marche :
Private Declare Sub SetVarTest Lib "C:\Documents and
Settings\Vincent\Bureau\test.dll" (ByVal Source As Long, ByVal nbytes As
Long, ByRef Destination As Any)
Tout ça pour ça... Bà maintenant je ferais un peut plus attention à mes
déclaration!!!
Merci encor à tous pour votre aide dans cette journée difficile qu'à été celle
d'hier.
Amicalement
Pensez "Réponse acceptée"
Vous n’avez pas trouvé la réponse que vous recherchez ?
Polack77
Messages postés1098Date d'inscriptionmercredi 22 mars 2006StatutMembreDernière intervention22 octobre 20191 26 sept. 2007 à 09:51
Merci bien à vous deux (ça marche ),
En faite il me manquais pas grand chose.
Heeee, par contre je ne sais toujours pas à cois corespond "@1".
Amicalement
Pensez "Réponse acceptée"
Polack77
Messages postés1098Date d'inscriptionmercredi 22 mars 2006StatutMembreDernière intervention22 octobre 20191 26 sept. 2007 à 11:20
Heee, en faite ça marche pas <!--[if gte vml 1]><v:shapetype
id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t"
path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" alt="" style='width:24pt;
height:24pt'/><![endif]--><!--[if !vml]--><!--[endif]-->
En tout cas merci BruNews pour ces deux liens mais je n'ai pas le temps de les lire tout de
suite (mais je me les mets sous le coude pour plus tard)
J'ai crée une form qui alloue 3 string les affiches avec leur adrs dans des
labels
Mon code qui ne marche pas :
VB :
<hr align="center" size="2" width="100%" />
Private Declare Function GetAdresse Lib "C:\Documents
and Settings\Vincent\Bureau\test.dll" (ByRef Variable As Any) As Long
Polack77
Messages postés1098Date d'inscriptionmercredi 22 mars 2006StatutMembreDernière intervention22 octobre 20191 26 sept. 2007 à 12:07
Etrange...
Si mes variables sont d'un autre type que 'string' ça semble fonctioné???
VB :
[...]
Dim TESTE As String
Dim TESTE2 As Integer
Dim TESTE3 As Long
[...]
TESTE = "Je fait des tests"
TESTE2 = 12
TESTE3 = 13
Label1.Caption = TESTE & " " & GetAdresse(TESTE)
Label2.Caption = TESTE2 & " " & GetAdresse(TESTE2)
Label3.Caption = TESTE3 & " " & GetAdresse(TESTE3)
[...]
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 26 sept. 2007 à 12:16
Et oui, c'est la gestion des variable de type string en VB6 qui t'induit en erreur.
Pour la plupart des variables en VB6, quand tu déclare une variable d'un type donné il s'agit bien d'une variable en mémoire.
Par contre, lorsque tu déclare une variable de type String, ce que tu as n'est pas une string mais un pointeur vers une zone mémoire qui contient les caractères composant la string. Cela est totalement transparent en VB6 pour l'uttilisateur car c'est VB qui se charge de gerer tout cela. Par contre les choses se compliques lorsque on sort de VB.
Regarde dans le document dont je t'ai donné le lien dans ma réponse, il y a tout un paragraphe sur la gestion des string entre VB et les api.
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 26 sept. 2007 à 12:22
Je teste sur Excel vu que je n'ai pas de VB.
Ben sur Excel (VBA) rien ne va, toujours la même adresse.
Sub Tester2()
Dim strA As String
Dim strB As String
Dim strC As String
Dim s As String
Dim v As Long
s = String(10, "A")
strA = "Je fait des tests et tout et tout"
strB = "Ce n'est pas la même adrs"
strC = "C'est que ca marche"
strA = strA & " " & GetAdresse(strA)
strB = strB & " " & GetAdresse(strB)
strC = strC & " " & GetAdresse(strC)
strA = strA & vbCrLf & strB & vbCrLf & strC
Debug.Print strA
v = GetAdresse(s)
strA = strA & " " & v
Debug.Print strA
Debug.Print v
End Sub
LE DEBUG DONNE:
Je fait des tests et tout et tout 1439168
Ce n'est pas la même adrs 1439168
C'est que ca marche 1439168
Je fait des tests et tout et tout 1439168
Ce n'est pas la même adrs 1439168
C'est que ca marche 1439168
Je fait des tests et tout et tout 1439168
Ce n'est pas la même adrs 1439168
C'est que ca marche 1439168 1439168
1439168
Ce qui tend à montrer que VB fait comme d'hab ce qu'il veut, surement copie dans le même buffer pour envoi à la DLL, on a aucun controle sur cela.
jrivet
Messages postés7392Date d'inscriptionmercredi 23 avril 2003StatutMembreDernière intervention 6 avril 201260 26 sept. 2007 à 12:23
Salut,
Simple petite question.
Pourquoi ne pas avoir utiliser Interop Form TollKit 2.0 proposé par M$ qui est supposé te permettre de développé des Formulaires et autres contrôles en VB.NET et utilisables dans VB6
Je n'est pas encore trop creusé mais cela a l'air assez bien.
Heeee, je n'ai pas trop le choix en faite, mes instructions sont de faire ça (en
plus j'ai déjà hue une réunion sur ce sujet avec le reste de l'équipe à qui
j'ai dit "pas de problème je m'y colle, ça sera vite fait", du coup je
vais passer pour un pas doué si je viens dire qu’"en final ce n'est pas
possible", je
continue de m'acharner au moins jusqu'en fin de semaine).
Merci pour le temps que tu à bien voulut m'accordé.
PS : casy Oui j'ai effectivement vue (sur le lient
que tu m'à transmit) que la gestion des string avais l'aire quelque peut
étrange en VB. Je me pencherais sur les string un peut plus tard (et si ce
n'est que ça je déclare un tableau de byte que je remplie avec la fonction asc
bouclé sur toute ma chaîne, l'objectif final n'est pas de faire passé des
strings de toute façon mais des tableau de structure de données)
Polack77
Messages postés1098Date d'inscriptionmercredi 22 mars 2006StatutMembreDernière intervention22 octobre 20191 26 sept. 2007 à 12:51
Je comance mes tests avec un tableau de byte, je ne fait plus rien avec les strings et j'essais de lire les adresses que l'on me renvoie.
Voila mon code C pour la DLL (bien sure j'ajoute la def en plus)
<hr size="2" width="100%" />void __stdcall SetVar(long AdrsALire, int LngEnOct, void* VariableARemplire)
{
while (LngEnOct != 0)
{
LngEnOct --;
*((char*)((long)VariableARemplire + LngEnOct)) = *((char*)(AdrsALire + LngEnOct));
}
}
<hr size="2" width="100%" />
Amicalement
Pensez "Réponse acceptée"
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 26 sept. 2007 à 14:24
OUPS et archi OUPS, on reprend depuis le début.
Comme quoi c'est mauvais l'interprété, j'y passe 5 mn et me voila pollué de faux concepts.
Il faut déréférencer l'afresse pour obtenir celle du BSTR (String de VB), donc fonction spéciale pour String:
DWORD __stdcall GetStrAdrData(DWORD *bst)
{
return (DWORD) *bst;
}
Polack77
Messages postés1098Date d'inscriptionmercredi 22 mars 2006StatutMembreDernière intervention22 octobre 20191 26 sept. 2007 à 15:18
Merci, mais je fait des tests avec des long (mais je me servirais sans doute de ça plus tard, merci).
A savoir : J'ai visual studio 2005 sur ma machine ce qui fait que si une erreur survient dans une dll je peut déboger directement sans stoper complétement mon execution, et il semble que ma DLL ne reçois pas les valeurs que je lui transmet. Je m'explique tout de suite.
Mon code à été de nouveau modifié (en suivant le tuto que casy à donné, ça : http://rp.developpez.com/vb/tutoriels/dll/) :
C (.cpp, pas de .h pour le moment)
<hr size="2" width="100%" />#include <windows.h>
#define export __declspec (dllexport)
export long __stdcall GetAdresse(void*);
export void __stdcall SetVar(long,short,void*);
long __stdcall GetAdresse(void* Variable)
{
return (long)Variable;
}
void __stdcall SetVar(long AdrsALire, short LngEnOct, void* VariableARemplir)
{
while (LngEnOct != 0)
{
LngEnOct --;
*((char*)((long)VariableARemplir + LngEnOct)) = *((char*)(AdrsALire + LngEnOct));
}
}
<hr size="2" width="100%" />
VB :
<hr size="2" width="100%" />Private Declare Function GetAdresse Lib "C:\Documents and Settings\Vincent\Bureau\test.dll" (ByRef Variable As Any) As Long
Private Declare Function SetVar Lib "C:\Documents and Settings\Vincent\Bureau\test.dll" (ByVal Adrs As Long, ByVal Lng As Integer, ByRef Variable As Any)
Dim TESTE As String
Dim TESTE2 As Integer
Dim TESTE3 As Long
Private Sub Form_Load()
Dim bidule As Long
TESTE = "Je fait des tests"
TESTE2 = 12
TESTE3 = 13
Label1.Caption = TESTE & " " & GetAdresse(TESTE)
Label2.Caption = TESTE2 & " " & GetAdresse(TESTE2)
Label3.Caption = TESTE3 & " " & GetAdresse(TESTE3)
SetVar GetAdresse(TESTE3), Len(TESTE3), bidule
Label4.Caption = bidule
End Sub
<hr size="2" width="100%" />Mon problème acctuel :
A l'execution de SetVar une erreur survient "Visual Basic a rencontré un problème et doit fermer. ..." là je clique sur "Débogage" et déboge à partir de Visual Studio 2005. Dans ce dernier je vois apparaitre mon code C et grande surprise les valeurs contenue dans mes variables n'ont rien à voir avec les valeurs que je veut transmétre. A savoir :
AdrsALire => 1308804
LngEnOct => -157
VariableARemplir => 0x00000004
Alors que dans VB
GetAdresse(TESTE3) => 1900388
Len(TESTE3) => 4
GetAdresse(bidule) => 1308844
Je convertie en ce momant toute ces valeurs en binaire/octal/hexa pour tenté de comprandre ce qui se passe (dé que je trouve je poste si quelqu'un trouve avant moi pouriez vous en faire de même, merci)
PS : µ$£¤^%§ de DLL à la µ£%ù^$ de µ$^ù%^!§ voir même plus...
Amicalement
Pensez "Réponse acceptée"