Traiter string vb par dll c/c++ (win32)

Soyez le premier à donner votre avis sur cette source.

Vue 11 161 fois - Téléchargée 640 fois

Description

Je présente ici une DLL spécialisée VB en ce sens que les String sont envoyées depuis VB en ByRef qui est le mode standard VB.
VB sait aussi passer un char*, on indique ByVal dans la déclaration API des params DLL.
Si on prend char* en param, on ne peut modifier les octets de la String qu'à condition d'avoir préparé un buffer assez large depuis VB (fontion Space()) par exemple.
On ne va donc pas analyser ce cas trivial.

Cas où on reçoit un String en param, il faut prendre *BSTR:
DLL: long __stdcall bnConcat(BSTR *bst1, BSTR *bst2, BSTR *bstRes)
VB : Declare Function bnConcat Lib "d:\bnStrs.dll" (s1 As String, s2 As String, sRes As String) As Long
- "d:\" est juste là pour mes tests, à enlever en prod.
Exemple très simple, on fait strcat de bst1 et bst2 puis résultat dans bstRes, bst1 et bst2 ne seront pas modifiés.
TRES IMPORTANT, bien regarder ce que valent bst1 et bst2 car peut-être non initialisés:

long __stdcall bnConcat(BSTR *bst1, BSTR *bst2, BSTR *bstRes)
{
char *pmem = 0, *c, *d;
DWORD len1 = 0, len2 = 0, count = 0;
if(*bst1) len1 = strlen((char*) *bst1);
if(*bst2) len2 = strlen((char*) *bst2);
count = len1 + len2;
if(!count) goto goResult;
pmem = (char*) HeapAlloc(GetProcessHeap(), 0, count + 1);
if(!pmem) {
count = 0; // pour SysAllocStringByteLen
goto goResult;
}
d = pmem; // initialisation du pointeur de copie
if(len1) {
c = (char*) *bst1; // ATTENTION EST DEREF (*) DE BSTR !!!
while(*d = *c) {d++; c++;} // ici copie en poussant mon pointeur de copie (d)
}
if(len2) {
c = (char*) *bst2; // ATTENTION EST DEREF (*) DE BSTR !!!
while(*d = *c) {d++; c++;}
}
goResult: // DOIT ETRE FAIT A TOUT COUP !!!
if(bstRes) SysFreeString(*bstRes);
  • bstRes = SysAllocStringByteLen(pmem, count); // FAIT UN BSTR POUR VB, si pmem = 0 valable idem

if(pmem) HeapFree(GetProcessHeap(), 0, pmem);
return count; // retourne strlen du concat
}

VB: j'ai mis un traitement d'erreurs mais inutile car la dll fait correctement son travail.
Dans tous les cas, si 'if(*bst1) len1 = ...' n'était pas fait, VB ne pourrait pas rattraper l'erreur et plantage complet du prog.
Vous pourrez tester en remettant l'initialisation ou non des String VB, ça marche toujours.

Sub TestConcat()
Dim R As Long
Dim st1 As String, st2 As String, stRes As String
On Error GoTo errConcat
' st1 = "youpi"
' st2 = "Hello"
R = bnConcat(st1, st2, stRes)
MsgBox stRes, vbInformation, R
Exit Sub
errConcat:
MsgBox Err.Description, vbCritical
End Sub

Second cas, retourner un String VB, idem on retourne BSTR:

BSTR __stdcall bnGetWinDir()
{
char buff[260];
DWORD len;
len = GetWindowsDirectory(buff, 260);
if(!len) buff[0] = 0;
return SysAllocStringByteLen(buff, len);
}

VB: Declare Function bnGetWinDir Lib "d:\bnStrs.dll" () As String

Sub TesteWindir()
Dim s As String
s = bnGetWinDir()
MsgBox s
End Sub

Si questions, demander.
Code VB dans bnStrs.txt, proj complet de la DLL sur VS 2003.

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
1
Date d'inscription
mardi 21 août 2012
Statut
Membre
Dernière intervention
21 août 2012

tres util et simple
Messages postés
1
Date d'inscription
vendredi 16 juin 2006
Statut
Membre
Dernière intervention
7 mai 2007

pour vb2005 il semble qu'il faut ecrire la declaration comme cela:

Declare Function bnConcat Lib "d:\bnStrs.dll" (ByRef s1 As String, ByRef s2 As String, ByRef sRes As String) As Long
Declare Function bnGetWinDir Lib "d:\bnStrs.dll" () As String

mais pour le reste tout reste valable, donc merci pour ce petit exemple ;-)
Messages postés
154
Date d'inscription
vendredi 20 août 2004
Statut
Membre
Dernière intervention
31 décembre 2007

Superbe Source Bravo et Merci 10/10
Messages postés
11
Date d'inscription
mercredi 1 décembre 2004
Statut
Membre
Dernière intervention
5 juillet 2005

En faite j'ai trouver

Faut faire dans un module..
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
28
Les 'Declare Function ...' devraient toujours se trouver dans un module général ce qui les rend accessibles partout, sinon dans un module objet tu dois ajouter 'Private' devant.
Ceci va bon idem dans un module général VBA dans Excel par exemple, c'est d'ailleurs ainsi que je les teste n'ayant plus de VB installé depuis fort longtemps.
Afficher les 8 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.