[C et VB] question sur les DLL

question sur les DLL [C et VB] - Programmation

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

Reply

Marsh Posté le 28-11-2001 à 11:37:14   

Reply

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.

Reply

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....)

Reply

Marsh Posté le 28-11-2001 à 15:13:18    

JE vois pas bien ou c'est que j'utilise ma fonction C !!!!

Reply

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 !!!! :)

Reply

Marsh Posté le 28-11-2001 à 17:33:31    

:(

Reply

Marsh Posté le 28-11-2001 à 19:35:18    

:( :(

Reply

Marsh Posté le 28-11-2001 à 21:36:16    

KarLKoX , je crois qu'il n'y a que toi qui peux m'aider !!!!!

Reply

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 :)

Reply

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.

Reply

Marsh Posté le 29-11-2001 à 09:52:27   

Reply

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.

Reply

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

Reply

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 .......
 
:)

Reply

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.

Reply

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!

Reply

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.

Reply

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 ?

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed