Newsgroup: it.comp.lang.visual-basic
Titolo: Debug e DLL

Ecco un buon modo per perdere delle ore di lavoro: sto realizzando un 
programma in VB6 che utilizza una DLL da me scritta in VC++6. Se compilo 
il programma VB e lo eseguo non c'e' nessun problema. Se invece lo eseguo 
da VB senza compilare ottengo l'errore di run-time 49: "convenzione di 
chiamata DLL non valida".
Ho verificato che il problema non si verifica se non ci sono parametri 
nella funzione della DLL.
La dichiarazione della funzione della DLL e':
extern "C" PROVA_API DWORD fnProva(DWORD);
Dove PROVA_API e' la macro definita dal wizard di VC.
Per quanto rigurada la definizione della funzione ho fatto la seguente 
prova:
PROVA_API DWORD fnProva(DWORD p){
	return p;
}
Nel programma VB ho inserito un modulo con la seguente dichiarazione:
Public Declare Function fnProva Lib "C:\prova\prova.dll" (ByVal p As 
Long) As Long
E la chiamata e' la seguente:
Text1.Text = fnProva(n)
Un esempio piu' semplice non mi sembra sia possibile, ma l'errore viene 
fuori puntualmente e solo se si lancia l'esecuzione da VB e non se si 
esegue l'EXE creato da VB.
Misteri di casa M$?
Vi prego di aiutarmi, devo finire il lavoro al piu' presto e ho gia' 
perso una marea di tempo per venire a capo di questo problema.
-- 
Andrea Polci
apo...@my-Deja.com

 extern "C" PROVA_API DWORD fnProva(DWORD);
prova mettendo _stdcall al posto di extern
Ciao
Faber




 
questo è un argomento interessante, vorrei documentarmi. hai qualche 
sito/suggerimento?
Ciao!
Si possono realizzare in questo modo delle classi istanziabili da VB?
--
Gio_F - mailto:
jg...@tiscalinet.it

 3) Ma adesso un vero programmatore con le palle crea oggetti COM con il
C++.
Non capisco. Se uso il C è per fare una funzione il + veloce possibile. Nel
momento che creo un oggetto COM, mi rallento tutto portandomi dietro
l'overhead del dialogo OLE.
O no?
Ciao
*Roby*

 l'overhead del dialogo OLE.
A dire il vero, il dialogo fra l'applicazione e una DLL che usi COM non č
cosě drammatico come ci si aspetterebbe. Ho provato a fare dei test - tempo
fa - e sostanzialmente non ci sono differenze fra chiamare una COM e una C
standard. Chiaramente, se poi nel codice della COM si sfruttano classi e
tutto l'ambaradan, allora č la DLL che ha problemi di ottimizzazione.
----------------------------------------------------------------
Stefano Minardi
zet...@mclink.it
----------------------------------------------------------------

 tutto l'ambaradan, allora è la DLL che ha problemi di ottimizzazione.
In effetti ha senso. Sarebbe interessante capire a questo punto quali sono i
vantaggi nell'usare COM senza sfruttare le possibilità di OLE.
Ciao
*Roby*

 vantaggi nell'usare COM senza sfruttare le possibilità di OLE.
Nessuno. Si può scrivere una DLL standard (non COM) che usa internamente le
MFC. Sono le classi usate in luogo delle struct, le collection in luogo
degli array, etc. etc. che appesantiscono il programma.
(*) A meno che non si sia sul filo del rasoio dei nanosecondi. In questo
caso, però, anziché il C conviene usare l'assembler.


 documentarli.
Ovviamente non ho una documentazione - non sono l'ISO e il mio era un test
improvvisato e subito cancellato, dopo aver letto una documentazione MS
nella quale si asseriva che non c'era quasi nessuna differenza (io almeno
dico che non c'è una *sostanziale* differenza). Tuttavia è una prova che si
può replicare molto facilmente perché consiste in questi semplici passi:
(a) creo una DLL standard in C che ha una funzione Pippo che fa qualcosa
(nella fattispecie eseguiva uno shift di bit su un Long, se ricordo bene,
quindi quasi niente).
(b) creo poi una DLL in VC++ che fa esattamente la stessa cosa.
(c) Da VB eseguo un loop di 50.000 chiamate a ciascuna delle due funzioni
con questi risultati: la dll standard viene eseguita più velocemente (se
ricordo bene 1,5 volte ca.) con un leggero miglioramento di prestazioni (non
apprezzabile a dire il vero) dopo la prima chiamata.
(d) In VB scrivo una DLL che ha una funzione Pippo che a sua volta chiama la
funzione Pippo nella DLL standard ed eseguo il test di prima: la funzione in
C gira qualcosa come 2-3 volte più velocemente (chiaramente la DLL in VB ha
l'overhead della COM più lo stesso della DLL in C).
Ora, a prescindere dalla finezza dei risultati (io usai il profiler, ma un
risultato a spanna si può vedere bene anche con un timer fine), su un PC che
allora era una 133 o un 166Mhz, il loop veniva eseguito in decine o poche
centinaia di millisecondi. Trattandosi di un loop di 50.000 ripetizioni e
considerato che la prima chiamata era la più costosa, mi chiedo se sia
apprezzabile la differenza visto che:
(1) se la funzione viene chiamata una tantum direi che non vale la pena di
andare a vedere se ci ha messo 2 o 3 millisecondi (anche perché su questo
possono influire altri processi: non si ha la certezza a priori del tempo di
esecuzione di una libreria).
(2) se la funzione è chiamata in un loop, la differenza è si notevole (come
si dice: è la somma che fa il totale), ma comunque si tratta di tempuscoli:
se si vanno a vedere quelli, allora forse sarebbe il caso di vedere come mai
si chiama la funzione in un loop invece di far eseguire il loop alla
funzione stessa.
Insomma, io vedo la cosa in questi termini: se si deve scrivere una
qualsiasi DLL - le cui funzioni avranno tempi di esecuzione mediamente
maggiori del tempo di chiamata e saranno utilizzate alla bisogna, non da un
programma di stress - non vedo sostanziale differenza fra una standard e una
COM. Se invece la DLL deve eseguire compiti time-critical molto pesanti -
mettiamo la compressione di un'immagine in Gruppo4 - allora la questione non
è quale interfaccia usare, ma quale linguaggio, perché in questo caso si fa
magari una sola chiamata, ma il lavoro è troppo anche per una procedura
scritta in C-che-più-ottimizzato-non-si-può. Per cui, prima di vedere come
risparmiare 1 ms sulla chiamata sarebbe meglio rivedere il codice delle
procedure scritte da noi: ci vuol poco a recuperare qualche millisecondo,
basta riguardasi tutti i loop.
Chiaramante ci sono casi in cui le cose sembrano molto diverse da quelle da
me prospettate. Ci sono DLL che per essere caricate ci mettono interi
secondi. In questi casi, però, bisogna considerare una serie di aspetti:
(a) la dll gira nello stesso thread del chiamante? Una chiamata nello stesso
thread (dopo il caricamento) è davvero veloce come la chiamata ad una dll
standard. Chiamare un thread diverso o anche un in-process ma late-bound è
decisamente più pesante.
(b) quanto è grande la DLL? Chiaramente ci vuole tempo per caricarla anche a
seconda delle dimensioni.
(c) la DLL ha RAM sufficiente? Se la quantità di codice - o la memoria
eventualmente allocata - fanno sì che venga spadellata roba sul disco,
chiaramente si rallenta tutto.
(d) la DLL esegue codice di inizializzazione complesso? Chiaramente un conto
è se l'inzializzazione esegue un semplice return(1), un conto se prima deve
crearsi tutti i suoi oggettini.
Un'ultima considerazione: una cosa che veramente odio delle DLL standard
chiamate da VB è che alla prima funzione chiamata il VB se le tira su e non
si sa se e quando le molla (secondo me solo quando si chiude il programma).
Almeno con le COM posso caricarle e scaricarle a mio piacimento.
(Oddio che pizza!-)
