Newsgroup: it.comp.lang.c++
Titolo: Funziona solo nella main()

Cari amici, secondo voi cosa posso dedurre da questo sintomo: un programma di 
poche righe (in particolare è la chiamata di una funzione che sta all'interno 
di una DLL) funziona solo se queste righe sono scritte direttamente nella 
main() mentre genera un GPF se sono messe in una funzione chiamata dalla 
main() stessa.
Ogni suggerimento è bene accetto.
Ciao a tutti.
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg
The EMG Music page:         
http://www.emagsoftware.it/emgmusic
 

 Ogni suggerimento è bene accetto.
Hai controllato le convenzioni di chiamata (per l'ordine dei parametri) 
e dimensione dei parametri (non do per scontato che la dll sia fatta in 
c/c++)?
-- 
la cultura è importante: 
http://www.libreriadellautomobile.it

 c/c++)?
Ma se fossero sbagliati non dovrebbe non funzionare anche nella main()? In 
ogni modo forse un problema c'č: non so se č corretto esprimere in C++ una 
"ByRef As String" come indirizzo di char *. Forse č lě che sbaglio?


 "ByRef As String" come indirizzo di char *. 
Siamo OT e tiro ad indovinare, hai scritto una funzione in C++ con 
interfaccia C e tenti di usarla con un linguaggio dot net.
In quel caso avrei una soluzione. Comunque puoi partire da qui: 
http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(vs.71).aspx
oppure:
http://msdn2.microsoft.com/en-us/library/aa720286(vs.71).aspx
Attento all'encoding. Nei test prova a passarti la stringa "òàùèì" per 
vedere che va tutto bene, sempre che tu non sia sicuro di avere a che 
fare solo con i caratteri dei primi 7 bit del latin-1 (o windows-1252, 
o utf-8, tanto sono gli stessi).


 interfaccia C e tenti di usarla con un linguaggio dot net.
Purtroppo dot net non c'entra per niente ma grazie lo stesso.


 Purtroppo dot net non c'entra per niente ma grazie lo stesso.
Allora il "ByRef As String" da dove deriva?
Giusto per curiosità.


 Giusto per curiosità.
Dalla documentazione di quella DLL (che non ho scritto io e della quale non ho 
il sorgente). Quello di cui sono certo è che non è per dot net in quanto in 
VB6 funziona regolarmente.


 Dalla documentazione di quella DLL 
qui (forse) trovi tutto quel che ti serve
http://support.microsoft.com/kb/187912/it
Nota che la convenzione di chiamata è __stdcall.
Comunque questo è una delle cose che odio, usare codice binario con 
scarsità di informazione. Secondo solo a maneggiare codice criptico.
Volendo qui trovi un poco di bibliografia 
http://www.visual-basic.it/articoli/agVB_VC.htm


 
http://www.visual-basic.it/articoli/agVB_VC.htm
Grazie molte, mi studio il tutto.


> 
http://www.visual-basic.it/articoli/agVB_VC.htm
se ne era parlato da poco con "Nabira" : per il passaggio delle 
stringhe via puntatore da/a VB6, il parametro va dichiarato
BYVAL ... As String.
Infatti le stringhe basico non sono AsciiZ (puntatore a array di 
caratteri terminati da null), ma un dato chiamato BSTR 
(puntatori a un descrittore di 2 o 4 byte che contiene al dato 
offset le dimensioni della stringa, è quindi una zona sacra e se 
ci scrivi sopra la DLL può crashare .... come pure se scrivi 
oltre le dimensioni allocate crasha potenzialmente tutto), e 
soltanto dopo il descrittore, contiguamente, sono contenuti i 
dati senza null finale.
Nel passaggio dal VB a C/C++ la clausola Byval indica al runtime 
di creare una stringa AsciiZ compatibile col formato antico 
WinApi, che è un AsciiZ o un unicode terminato da null (VB 6 
dovrebbe ragionare già in unicode ma non sono strasicuro).
Nel passare una stringa C al VB, nuovamente penso dovresti 
dichiararla byval, in modo che il runtime scandisca la stringa 
AsciiZ fino a trovare il null, determini la dimensione e a quel 
punto crei un descrittore BSTR vuoto e lo iniazializzi, copiando 
infine i dati veri e propri. C'è un certo overhead, ma la copia 
fisica è eseguita ove possibile con asm rep scasw e rep movsw 
(operazioni stringa piuttosto veloci)
Le stringhe di VB sono da sempre amore e odio ognqualvolta devi 
raccordarle ad altro, perchè il runtime le tiene gelosamente 
dentro e spostarle o riallocarle è quasi impossibile (già solo 
leggerle correttamente non è immediato).
Se ti può servire da lato VB6, StrPtr(valorestringa) restituisce 
un puntatore long consistente al primo carattere dei DATI 
effettivi, mentre VarPtr restituisce un puntatore al descrittore 
(ossia 4 byte più basso), di cui non te ne fai niente se non 
hacking vario più o meno funzionante.
ciao
Soviet


 BYVAL ... As String.
Grazie ma forse non mi sono spiegato bene io inizialmente: io uso il C per 
accedere ad una DLL che forse è scritta per funzionare solo con VB. Quindi 
dovrei fare il contrario di quanto mi consigli.


 
Si ma alla fine il tuo problema è QUASI lo stesso:
devi passare la BSTR da C a VB, o detta meglio devi passare una stringa 
secondo le regole COM (che sono assai complesse)
Ci deve essere in giro un articolo chiamato "strings the ole way" o 
qualcosa del genere di Bruce McKinney (scrisse alcuni famosi libri su 
VB) che spiega i dettagli. Prova a googlare.
In pratica non dovrebbe essere complicato: ti allochi una BSTR usando le 
funzioni COM (tipo SysAllocString o alcune classi tipo le CString MFC la 
wrappano gratis) e passi a VB il puntatore alla variabile che ottieni.
Su due piedi non ricordo chi deve fare pulizia, anche perchè dipende 
dalla dichiarazione precisa COM (se in, out, in/out, byval, byref, 
sehaigliocchiverdi, ... e altre mille regolette che trovi nell'articolo 
di cui sopra). Se ti serve la dichiarazione COM vedi se assieme alla dll 
hai una tlb ed esaminala con OLEView.
Buona fortuna

 Si ma alla fine il tuo problema č QUASI lo stesso:
Vero. Grazie.


 secondo le regole COM (che sono assai complesse)
Funziona:
BSTR cDato = SysAllocStringByteLen( NULL, 258 );
FunzioneDellaDLL( &cDato );
SysFreeString( cDato );
Grazie a tutti.
