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

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

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.