question sur les DLL [C et VB] - Programmation
Marsh Posté le 28-11-2001 à 12:00:24
Effectivement, retourner un pointeur sur char ne marche pas avec VB. Tu doit faire une fonction qui prend en paramettre l'adresse du pointeur et copier son contenue dans une variable string que tu retourneras.
Exemple :
' On a changé la declaration pour retourner l'adresse du pointeur , d'ou le Long
Private Declare Function ConvCStringToVBString Lib "kernel32" Alias "lstrcpyA" (ByVal lpsz As String, ByVal pt As Long) As Long
'Utilisation :
' dim lpstrString as long
' dim chaine as string
' chaine = "test"
' lpstrString = GetStringFromPointer(StrPtr(lpstrString))
Public Function GetStringFromPointer(ByVal lpString As Long) As String
Dim zpos As Long
Dim s As String
s = String(255, 0)
ConvCStringToVBString s, lpString
' Look for the null char ending the C string
zpos = InStr(s, vbNullChar)
s = Left(s, zpos - 1)
GetStringFromPointer = s
End Function
En esperant que ca marche de ton coté, j'ai souvent a faire des DLL en C/C++, cette méthode a toujours fonctionnée.
Marsh Posté le 28-11-2001 à 15:10:02
KarLKoX a écrit a écrit : Effectivement, retourner un pointeur sur char ne marche pas avec VB. Tu doit faire une fonction qui prend en paramettre l'adresse du pointeur et copier son contenue dans une variable string que tu retourneras. Exemple : ' On a changé la declaration pour retourner l'adresse du pointeur , d'ou le Long Private Declare Function ConvCStringToVBString Lib "kernel32" Alias "lstrcpyA" (ByVal lpsz As String, ByVal pt As Long) As Long 'Utilisation : ' dim lpstrString as long ' dim chaine as string ' chaine = "test" ' lpstrString = GetStringFromPointer(StrPtr(lpstrString)) Public Function GetStringFromPointer(ByVal lpString As Long) As String Dim zpos As Long Dim s As String s = String(255, 0) ConvCStringToVBString s, lpString ' Look for the null char ending the C string zpos = InStr(s, vbNullChar) s = Left(s, zpos - 1) GetStringFromPointer = s End Function En esperant que ca marche de ton coté, j'ai souvent a faire des DLL en C/C++, cette méthode a toujours fonctionnée. |
Merci, je vais essaye ca!! (meme si j'ai pas tout compris....)
Marsh Posté le 28-11-2001 à 15:13:18
JE vois pas bien ou c'est que j'utilise ma fonction C !!!!
Marsh Posté le 28-11-2001 à 15:28:10
Prenons une fonction C toute simple:
char* _stdcall concat(char* a,char* b)
{
return concat(a,b);
}
cette fonction est dans ma DLL.
Dans mon prog VB, j'ai 2 champs text chaine et motif
J'appelle ma fonction comme ca:
Option Explicit
Private Declare Function concat Lib "MYDLL.dll" (ByRef a As String, ByRef b As String) As String
Private Sub bouton_Click()
MsgBox concat(motif, chaine)
End Sub
Comment faire pour que ca marche???
Merci.....(je suis un peu perdu la !!!!
Marsh Posté le 28-11-2001 à 21:36:16
KarLKoX , je crois qu'il n'y a que toi qui peux m'aider !!!!!
Marsh Posté le 29-11-2001 à 07:48:31
Ne passe pas des chars (ASCII), vb c'est de l'UNICODE.
Au lieu de passer des chars dans ta fonction, passe des BSTR.
Apres tu as des fonctions en C qui transforme un BSTR en char et inverssement, mais je ne m'en rappelle plus
Marsh Posté le 29-11-2001 à 09:52:27
L'exemple donné permettait de recevoir correctement la valeur contenu dans le pointeur char que tu retournes, car il y a de forte chance que ca plante VB.
Sinon yop a raison, il vaut mieux passer par un BSTR ou autre (LPSTR ici) aussi bien pour les arguments que pour la valeur retournée.
J'essayerais de voir ca plus en détail ce soir.
Marsh Posté le 29-11-2001 à 18:58:41
Voila en gros ce que ca devrait donner :
// Partie C
#include <windows.h>
#include <string.h>
#define WINEXPORT __declspec(dllexport) WINAPI
LPSTR WINEXPORT Concat(LPSTR chaine1, LPSTR chaine2)
{
return strcat(chaine1,chaine2);
}
' Partie VB : ajouter un command button
Private Declare Function concat Lib "Concat.dll" Alias "_Concat@8" (ByVal a As String, ByVal b As String) As Long
Private Declare Function ConvCStringToVBString Lib "kernel32" Alias "lstrcpyA" (ByVal lpsz As String, ByVal pt As Long) As Long ' Notice the As Long return value replacing the As String given by the API Viewer.
Public Function GetStringFromPointer(lpTest As Long) As String
Dim zpos As Long
Dim s As String
s = String(255, 0)
ConvCStringToVBString s, lpTest
zpos = InStr(s, vbNullChar)
s = Left(s, zpos - 1)
GetStringFromPointer = s
End Function
Private Sub Command1_Click()
Call ConcatChaine("un", "test" )
End Sub
Private Sub ConcatChaine(ByVal chaine1 As String, ByVal chaine2 As String)
Dim chaine As String
chaine = GetStringFromPointer(concat(chaine1, chaine2))
MsgBox chaine
End Sub
Cette méthode fonctionne.
Marsh Posté le 30-11-2001 à 11:43:34
OK,
Mais mon prog C est deja ecrit avec des char * !
Je peut effectivement changer les char* en BSTR mais apres, mon programme fait des operation sur les char*.
Est que les BSTR joue le meme role que les char* (et on peut faire les meme operation dessus???), ou faut -il que je les transforme au paravant en char* (comment ???).
Merci
Marsh Posté le 30-11-2001 à 13:30:32
C'est la meme chose a part que le char c'est 1 octet,
le BSTR c'est 2 octets ....
Les 2 servent coder des chaines de caracteres.
Il y a des fonctions de conversion entre les 2, cependant, toutes les opreations de base strcpy, strcat, ... on leur equivalent .... dans MSDN, tu trouveras les correspondances.
Toujours afin que tu puisse dialoguer avec VB, il faut impreativement lui passer des BSTR car vb est full UNICODE, donc ne sais pas ce que c'est un char .......
Marsh Posté le 30-11-2001 à 20:59:14
Bon cet exemple devrait plus te plaire je pense :
#include <string.h>
char* __stdcall Concat(char* chaine1, char* chaine2)
{
return strcat(chaine1,chaine2);
}
Ajouter un *.DEF qui doit ressembler à ca :
EXPORTS
MYFUNC =_Concat@8 ; Alias
_Concat@8 ; StdCall et non pas __cdecl
La partie VB ne change pas, le tout devrait fonctionner maintenant.
Marsh Posté le 04-12-2001 à 21:42:00
KarLKoX a écrit a écrit : Bon cet exemple devrait plus te plaire je pense : #include <string.h> char* __stdcall Concat(char* chaine1, char* chaine2) { return strcat(chaine1,chaine2); } Ajouter un *.DEF qui doit ressembler à ca : EXPORTS MYFUNC =_Concat@8 ; Alias _Concat@8 ; StdCall et non pas __cdecl La partie VB ne change pas, le tout devrait fonctionner maintenant. |
Merci, ca a l'air de bien fonctionner!!!!
Question subsidiaire:
A quoi correspont le @8?
Comment ajouter d'autres fonctions dans le fichier .DEF ?
Merci pour tout!
Marsh Posté le 05-12-2001 à 02:34:41
le "@8" est la décoration suivant la convention de nommage en PASCAL. Tu l'as dans le mapfile généré (si tu as coché l'option pour generer un mapfile). D'apres moi, ca doit correspondre au nombre d'octet que la fonction a besoin (suivant la taille des arguments et de la valeur de retour) mais c'est a vérifier.
Pour les autres fonction, tu fais pareil, il suffira juste de changer l'alias (utilise dependency walker pour te faciliter la tache), ca ne devrait pas poser de probleme.
Marsh Posté le 05-12-2001 à 11:18:51
KarLKoX a écrit a écrit : le "@8" est la décoration suivant la convention de nommage en PASCAL. Tu l'as dans le mapfile généré (si tu as coché l'option pour generer un mapfile). D'apres moi, ca doit correspondre au nombre d'octet que la fonction a besoin (suivant la taille des arguments et de la valeur de retour) mais c'est a vérifier. Pour les autres fonction, tu fais pareil, il suffira juste de changer l'alias (utilise dependency walker pour te faciliter la tache), ca ne devrait pas poser de probleme. |
Merci!
Autre question: a quoi ca sert de passer par un alias ?
Marsh Posté le 28-11-2001 à 11:37:14
Voila mon probleme:
J'ai une fonction C qui prends 2 char* en parametre et qui retourne un char*
J'ai cree ma DLL.
Sous VB, je declare ma fonction avec le type String.
=> ca marche pas !!!
Faut il utiliser un autre type que string?
Est-il imossible de faire ca?
Comment faire?
D'avance merci