Newsgroup: it.comp.lang.visual-basic
Titolo: DLL, visualbasic 6, visualc++ 6, stringhe

PROBLEMA: non riesco a passare stringhe e interi a una dll fatta in vc,
elaborarli nella dll e
ritornare i valori al vb.
O sono imbranato io o e' ora di aggiungere un filettino al sito comune :-D.
Io faccio la mia parte:
sono 2 giorni che cerco nell' MSDN e in google... e non ho risolto nulla.
ho anche scaricato due file dall'archivio comune... e i file si compilano
male con vb6 e vc++ 6 (nel .txt allegato erano stati compilati con la ver
4)...
come tutti gli esempi trovati con google.
si parla di varptr, BSTR, etc... io voglio usare (per ora) nella dll solo
char * e int, senza mfc.
per non fare perdere tempo a nessuno, vi posto un codice che ho scritto per
l'occasione:
mydll.dll----------------------DLL----------------
#include <stdio.h>
__declspec(dllexport)   int myfunc(char *str1, char *str2, int a, int *b);
int myfunc(char *str1, char *str2, int a, int *b)
{
 int i,j;
 i=j=0;
 while(str1[i]!='\0') // trova la fine di str1
  i++;
 while((str1[i++]=str2[j++])!='\0') // accoda str2 a str1
  ;
 *b=a*a;
    return 100;
}
mydll.exe----------------------CODICE C PER PROVARE LA DLL. FUNZIONA.
#include <stdio.h>
__declspec(dllimport) int myfunc(char *str1, char *str2, int a, int *b);
void main(void)
{
 int res;
 char str1[20]="tarta"; //al ritorno sara "tartaruga"
 char *str2="ruga";
 int a=4;
 int b;                 //al ritorno sara 16
 res = myfunc(str1, str2, a, &b); //myfunc ritorna sempre 100
 printf("str1=%s, b=%d, res=%d\n", str1, b, res);
}
-------------------CODICE VB PER PROVARE LA DLL... NON FUNZIONA
Option Explicit
Private Declare Function myfunc Lib "mydll.dll" (ByVal str1 As String, ByVal
str2 As String, ByVal a As Integer, b As Integer) As Integer
Private Sub Command1_Click()
Dim res As Integer
Dim str1 As String
Dim str2 As String
Dim a As Integer
Dim b As Integer
str1 = "tarta" ' ? devo fare & chr(0)? devo fare & "         " ?
str2 = "ruga"
a = 4
res = myfunc(str1, str2, a, b)
MsgBox "str1=" & str1 & " b=" & b & " res=" & res
'Errore di run-time '49':
'convenzione di chiamata DLL non valida
End Sub
------------------------------FINE
quando lancio il programma in vb
'Errore di run-time '49':
'convenzione di chiamata DLL non valida
ragazzi, vi assicuro, tutti i txt e doc che ho trovato per fare sto lavoro,
non riesco a
farli girare con vb6 e vc++6....
grazie
ferdyz

> __declspec(dllimport) int myfunc(char *str1, char *str2, int a, int *b);
usa questa
 __declspec(dllexport) int myfunc(char *str1, char *str2, int a, int *b);
 Private Declare Function myfunc Lib "mydll.dll" ( str1 As String,
str2 As String, ByVal a As long, b As long) As long
poi hai fatto degli errori piuttosto gravi ...
1)non puoi accodare un'altra stringa in quanto non è detto ci sia spazio..
2)come sembra gia sai,si usano le bstr per accodare in quanto vanno cambiati
dati nel descrittore della stringa.La stringa da passare puoi dichiararla in
questo modo  Dim str1 As String * numero_massimo_caratteri  (dovrebbe
funzionare )
3) vb usa 2 byte per gli integer invece vc 4
ciao


ops dimenticavo stdcall (magari inseriscilo nelle opzioni tanto per le dll
si "dovrebbe" usare sempre stdcall)
oppure :
__declspec(dllexport)  int __stdcall myfunc(char *str1, char *str2, int a,
int *b);
ciao

 3) vb usa 2 byte per gli integer invece vc 4
ops! usero i long.
ADDENDUM:
dal msdn "Conversione di dichiarazioni C in Visual Basic"
fanno riferimento a tutti i tipi c... tranne che ai char * :-)
dicono giusto che un
LPSTR e LPCSTR si traduce in vb in ByVal variabile As String
e in wtypes.h c'e' scritto che:
typedef char CHAR;
typedef /* [string] */ CHAR __RPC_FAR *LPSTR;
quindi un LPSTR equivale a char * e quindi ho scritto bene la
dll senza usare i bstr?
per quello che ho capito
se nella dll uso char * == LPTR,  in vb si usa myfunct(ByVal variabile As
String, ...
se nella dll uso BSTR, in vb si usa myfunct(ByRef variabile As String, ...
peccato che a me non funzioni :)
grazie per l'interesse
ferdyz

 LPSTR e LPCSTR si traduce in vb in ByVal variabile As String
lpstr è un puntatore e puoi tradurlo come str as string (ci pensa vb a
convertire la stringa)
non penso che vb permetta un passaggio per valore della stringa (è da
verificare ) però è sempre sconsigliabile secondo me.
Usa sempre e cmq "stringa as string" senza il byval ...
ps. queste semplici dll le ho semrpe scritte ed hanno semrpe funzionato
,secondo me hai dei banalissimi errori che ti sfuggono.
ciao

 As String, ...
No, devi utilizzare ByRef (oppure non specificare nulla) *in
entrambi* i casi.
Ciao.
--
BSD is for UNIX-lovers -- linux is for Windows-haters.

 entrambi* i casi.
Non so cosa mi è preso, ma ho scritto una stupidaggine
terribile (e meno male che me ne sono accorto...).
Nel caso di char* devi utilizzare ByVal (e non ByRef come
avevo erroneamente scritto prima).


 avevo erroneamente scritto prima).
veramente era giusto prima...
cmq penso sia la stessa cosa ...non credo che vb passi per valore..
"stringa as string"
ciao

 valore..
No, le stringhe vanno passate, sia in ingresso che in uscita,
per valore (ByVal). L'ambiente VB si occupa di tutto.


 ,secondo me hai dei banalissimi errori che ti sfuggono.
TROVATO
non era la dichiarazione che non andava, ma la definizione!
__declspec(dllexport)  int __stdcall myfunc(char *str1, char *str2, int a,
int *b);
int __stdcall myfunc(char *str1, char *str2, int a, int *b) //<--- MANCAVA
QUI  __stdcall
{
...
non so perche la vuole anche nella definizione... ma la vuole. almeno nel
mio pc.
ora il vb aggancia la dll! grazie Franco per l'aiuto che mi hai dato.
dal momento che la stringa ritornata dal C e' null terminata, ho fatto
due routine, una che aggiunge il null, una che lo toglie
-------------------------
str1dapassare = pre_str_dll(str1)
res = myfunc(str1dapassare, str2, a, b)
str1 = post_str_dll(str1dapassare)
---------------------
Public Function pre_str_dll(s As String) As String
pre_str_dll = s & Chr(0)
End Function
---------------------
Public Function post_str_dll(s As String) As String
Dim i As Integer
Dim trovato As Boolean
Dim car As String
trovato = False
i = 1
post_str_dll = ""
While trovato = False
    car = Mid(s, i, 1)
    If car = Chr(0) Then
        trovato = True
    Else
        post_str_dll = post_str_dll & car
    End If
    i = i + 1
Wend
End Function
----------------------------
se hai voglia ti chiedo altre due cose. tu avevi scritto:
"ops dimenticavo stdcall (magari inseriscilo nelle opzioni tanto per le dll
si "dovrebbe" usare sempre stdcall)"
si usa davvero cosi spesso stdcall o equivalentemente lo switch /Gz, al
posto della cdecl di default?
se devo chiamare una dll, come faccio a sapere quale convenzione di chiamata
e' stato usato?
ciao!

 Public Function post_str_dll(s As String) As String
Public Function post_str_dll(ByVal s As String) As String
Ciao.


 per valore (ByVal). L'ambiente VB si occupa di tutto.
uso queste definizioni quasi tutti i giorni ed ho fatto lo stesso errore....
(che pirla 2 volte)
... si vero è byval
ciao

 ritornare i valori al vb.
Solo una precisazione per approfondire:
http://groups.google.it/groups?hl=it&lr=&ie=UTF-8&threadm=wglR8.61323%24TS.1
715684%
40news1.tin.it
&rnum=1&prev=/groups%3Fhl%3Dit%26lr%3D%26ie%3DISO-8859-
1%26q%3Dzanna%2Bdll%2Bpassare%26btnG%3DCerca%2Bcon%2BGoogle%26meta%3Dgroup%2
53Dit.comp.lang.visual-basic
Ciao

 53Dit.comp.lang.visual-basic
diventa il ben più maneggevole
http://makeashorterlink.com/?S37D23D51


 ... si vero è byval
Noto che in estate inoltrata errori del genere capitano più
spesso. Sarà il bisogno di una vacanza (io per primo)...
Ciao.


  Devo necessariamente assegnare una stringa prima ?
fai cosi
res=funzione("nome_da_passare" & chr(0))
per il mess di prima, bisogna mettere __stdcall sia nella definizione, sia
nella dichiarazione
della funzione.
ciao