Newsgroup: it.comp.lang.c++
Titolo: DLL da ZERO in VB e VC++ c'è un libro ?

Esiste un libro che spieghi dettagliatamente come si creano le DLL in
VC++ e come si richiamano (soprattutto da VB)?
Sapete farmi un esempio "stupido" sull'argomento?
--
Posted from 
mail.tin.it
 [194.243.154.49]
via Mailgate.ORG Server - 
http://www.mailgate.org

Sapete farmi un esempio "stupido" sull'argomento?
Eccone uno semplicissimo.  Crea col Wizard un progetto di
tipo "Win32 Dynamic-Link Library", chiamalo PIPPO, e aggiungi
il singolo sorgente pippo.cpp:
extern "C" __declspec(dllexport)
long __stdcall pippo(long i) {
    return i*3;
}
Fai il build, e otterrai, ad esempio del sottodirectory Debug,
un file chiamato PIPPO.DLL.  Per comodita`, copialo da
qualche parte nella tua PATH, o in un directory di sistema,
tipo ad esempio C:\WINDOWS.
Ora apri VB, fai un'EXE standard, nel form metti un Text,
una Label, e un Command tutti con nomi di default, e
scrivi il seguente codice:
Option Explicit
Private Declare Function pippo Lib "pippo.dll" _
    Alias "_pippo@4" (ByVal i As Long) As Long
Private Sub Command1_Click()
    Dim i As Long
    Label1 = CStr(pippo(CLng(Text1)))
End Sub
Salva e fai girare -- immettendo un numero nel Text
e cliccando il Command, vedrai il numero triplicato
nella Label -- il calcolo e` stato fatto dalla DLL.
Spero che non ci siano problemi per te su semplici
dettagli VB come la CLng e la CStr (io preferisco
sempre chiedere esplicitamente le conversioni di
tipo quando occorrono, non mi fido di quelle che il
VB fa "di default"...!), e che i problemi siano tutti su
quella misteriosa Declare; questa e` la parte che
viene spiegata piuttosto bene nel capitolo che ti
indicavo dei Books Online del Visual Basic.
Se il C++ esporta la funzione pippo includendo un
apposito file .DEF, allora non occorre piu` in VB
quella clausola Alias, perche` la funzione viene
allora esportata proprio con il nome "pulito", cioe`
"pippo"; se non si vuole usare un .DEF, quello che
viene esportato e` il nome "decorato", cioe` con
quella "appendice" "@4" che indica che la funzione
accetta un totale di 4 byte di argomenti (un long,
per valore).  Inoltre, avendo il .DEF, ci si puo`
risparmiare in C++ la __declspec(dllexport).  Il
capitoletto "Module-Definition (.DEF) files" della
guida in-linea del VC++ (sotto VC++ Programming
Guide / Compiling and Linking / Details) da` tutte
le specifiche del formato dei .DEF, comunque qui
bastera` aggiungere al progetto un file di testo
chiamato PIPPO.DEF contenente:
EXPORTS
    pippo
Aggiungilo dunque, togli il __declspec(dllexport)
dal sorgente C++, ricostruisci, ricopia di nuovo la
DLL sovrascrivendo la copia precedente; in VB,
togli la clausola Alias; fai girare nuovamente il VB,
e vedrai che tutto funziona ancora come prima.
Spero che possa bastarti per cominciare...!
Alex

Grazie mille per i suggerimenti. 
Fino ad ora ho capito tutto (vorrei vedere!!).
Il mio scopo è quello di trasformare alcuni eseguibili distinti
(sviluppati con VC++5) in 
altrettante DLL che richiamo da un'altro eseguibile sviluppato in VB5.
Fino ad ora riesco a far funzionare il tutto chiamando da VB
direttamente gli eseguibili,
ma il tutto è un pò pesante e sinceramente poco bello. È possibile
trasformare questi EXE in DLL
(tieni conto che questi EXE hanno finestre, pulsanti etc..)? Se si come
si fa?
Ringrazio anticipatamente.
Francesco.


si fa?
Si, e` possibile.  Non ci chiarisci se hai usato MFC, o API
nude, o che altro.  Supponendo che siano MFC: devi settare
vari switch per "dire" alle MFC che stanno in una DLL --
cosi`, invece dell'entry point WinMain, sanno di doversi
"impadronire" di DllMain -- da li` chiamano la InitInstance
del tuo oggetto applicativo, eccetera eccetera.
Per i dettagli, il mio suggerimento e`: chiedi al wizard di
generarti due progetti MFC, uno EXE e uno DLL, e fai il
confronto delle differenze dei vari settaggi.
Il problema piu` delicato: le MFC hanno dello "stato
globale", e al massimo UN modulo (EXE o DLL) in
un dato processo puo` permettersi di averlo davvero
globale -- se vi e` piu` di un modulo che usa MFC
dalla stessa shared library, ci sono varie macro e
funzioni che ti tocca chiamare per la gestione.  La
soluzione semplice: linka staticamente le MFC a
ciascuna delle DLL.
Altri possibili trabocchetti: e` facile confondersi
fra HINSTANCE, o HMODULE che dir si voglia,
del _modulo corrente_, e _del processo_ (infatti
quest'ultimo coincide con quello del modulo EXE).
Se hai sempre usato "religiosamente" e a proposito
le AfxGetResourceInstance, ecc, no problem (o,
se non fai nulla che richieda l'accesso a HMODULE
o HINSTANCE, tipo LoadResource ecc ecc); e`
piu` probabile che qualche magagna la troverai.
Il progetto, dunque, e` fattibile ma non leggero.
Gia` che ci sei, accertati, se vuoi il mio consiglio,
di supportare COM (specificamente Automation)
nei tuoi moduli, EXE o DLL che siano, cosi` e`
del tutto trasparente a Visual Basic quale dei due
casi si ponga (eccetto per le prestazioni, ecc, se
scambi fra cliente VB, e tuo modulo, molti, ma
*MOLTI* dati).  So che MFC fra le varie cose ha
supporto per questo, ma non l'ho mai usato sul
serio (il COM l'ho sempre fatto, o "a mano", o con
ATL, che e` un'altra libreria benche` possa anche
essere usata _assieme_ a MFC).  Il punto e` che
COM (fra cui Automation) e` "il" modo giusto per
comunicare fra moduli separati in Windows, e ha
tanti vantaggi rispetto ai tanti altri metodi, tali da
rendere ampiamente giustificato l'investimento in
apprendimento e ristrutturazione del codice.  Fra
i vari vantaggi, la "trasparenza" fra implementazioni
in EXE e in DLL...
Alex