Newsgroup: it.comp.programmare.win32
Titolo: DLL: dov'e' l'errore?

Mi scuso sin da ora per la lunghezza del messaggio, e spero di non
essere troppo OT.
Il problema e' il seguente: ho costruito in VC6 (attraverso il Wizard)
una semplicissima DLL, il cui codice e' il seguente:
#include "stdafx.h"
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
    return TRUE;
}
__declspec(dllexport) long WINAPI myfunction(long parameter)
{
 return (parameter * 2);
}
Nel .h ho inserito la seguente dichiarazione (forse superflua):
__declspec(dllexport) long WINAPI myfunction(long parameter);
Ho costruito un programmino di test in MFC che richiama la funzione
myfunction (linkando il .LIB e inserendo la __declspec(dllimport) long
WINAPI myfunction(long parameter);), e tutto funziona tranquillamente.
Il problema nasce quando cerco di accedere alla myfunction da un
programma VB6. Nel modulo ho inserito la seguente dichiarazione:
Declare Function myfunction Lib
"D:\Progetti\MyDLL\FirstDLL\Prova\Debug\TestDll.dll" (ByVal parameter
As Long) As Long
ma, quando da codice richiamo la myfunction, si verifica un errore del
tipo: impossibile trovare l'entry point per la funzione myfunction. Il
path della DLL e' corretto, tipo e numero di parametri di myfunction
coincidono con quelli che passo in fase di chiamata, dunque c'e'
qualcosa che non so e che mi genera l'errore. Ringrazio
anticipatamente chi potra' darmi un suggerimento. Buona giornata e
buon lavoro!
--
Massimo Fauro

 ha scritto nel messaggio
news:8jeulg$9t0$1...@bw107zhb.bluewin.ch...


 una semplicissima DLL, il cui codice e' il seguente:
Devi rivestire la tua funzione di un extern "C" cosi` che il
compilatore non ne "decori" il nome, come, per permettere
overload e simili, deve fare per funzioni "C++ veraci".  Insomma:
extern "C"
{
 __declspec(dllexport) long WINAPI myfunction(long parameter)
 {
  return (parameter * 2);
 }
}
e lascia perdere il .h (o duplica la extern "C" anche li`).
Infatti, come puoi vedere con un quickview, o dumpbin, ecc ecc,
sulla tua DLL, se non metti extern "C" il vero nome della tua
funzione non e` myfunction ma una stringa piu` complessa, che
codifica sia il nome myfunction sia aspetti come il numero e
tipo di parametri; comodissimo per chiamarla da C++ (dello stesso
produttore:-), inusabile da altri linguaggi (o altri release C++).
Alex

Ho provato ad introdurre la extern "C" come avete detto voi, ed il
risultato non cambia: il programma di test in MFC continua a
funzionare tranquillamente, mentre il programma VB mi da' lo stesso
errore di prima (impossibile trovare l'entry point per la funzione
myfunction).
Ho provato a fare anche la seguente modifica: ho eliminato la macro
WINAPI (ex  '_far_pascal', se non erro) dalla dichiarazione della
funzione nel codice della DLL. MFC continua a funzionare, ma stavolta
il programma VB mi da', in corrispondenza della chiamata alla funzione
(result = myfunction(numero), con numero As Long), l'errore 'Bad DLL
calling convention'. L'Help on Line, fra le varie cause/soluzioni, mi
da' i seguenti suggerimenti
Il programma sta chiamando una routine in una DLL senza utilizzare la
convenzione di chiamata StdCall.
L'istruzione Declare per una DLL Windows include CDecl.
Vi dice niente tutto cio'? A me (SIGH!) no....
--
Massimo Fauro

 L'istruzione Declare per una DLL Windows include CDecl.
???
L'uso di type libraries e` secondo me comunque un'idea migliore;
vedi il libro Hardcore Visual Basic, incluso tra l'altro nell'MSDN.
Non ti ovvia al fatto di DOVERE usare STDCALL, o WINAPI che dir
si voglia, ma ti risolve sostanzialmente tutti gli altri problemi.
(Il COM di solito usa implicitamente le type libraries [e la
STDCALL!] ed e` anche per questo che e` cosi` COModo e potente).
Alex

Posto questo messaggio per chiunque avesse lo stesso problema.
Allora, come dicevano Alex e Martino ho introdotto la extern "C" prima
della dichiarazione della funzione all'interno del codice della DLL.
Questa 'direttiva' dovrebbe consentire al compilatore di non decorare
il nome della funzione, per rendere possibile l'accesso alla stessa
funzione da parte di altri moduli attraverso una chiamata 'per nome'.
A quanto pare, per il Visual Basic non e' sufficiente, e infatti
continuava a dirmi che non riusciva a trovare l'entry point per la
funzione che io chiamavo. Ho provato a modificare la Declare del
modulo Visual Basic, introducendo un Alias che specificasse un
riferimento alla funzione all'interno della DLL (numero ordinale della
stessa, cioe' 1) e magicamente questa cosa gli e' piaciuta. Per la
cronaca, la sintassi della Declare nel modulo Visual Basic e' la
seguente:
Declare Function myfunction Lib
"D:\Progetti\MyDLL\FirstDLL\Prova\Debug\TestDll.dll" Alias "#1" (ByVal
parameter As Long) As Long
La domanda, adesso, diventa un'altra: e se io non conoscessi a priori
l'ordinale della funzione all'interno della DLL, come farei a
chiamarla? Mah...
Saluti
--
Massimo Fauro

 esempio un long).
Verissimo Alex, il nome e' proprio ancora decorato alla moda Pascal. E
ti diro' di piu': per farglielo accettare, devo aggiungere un
underscore prima del nome stesso, cioe':
... Alias "_myfunction@4"...
Comunque, sembra funzionare anche con l'ordinale, come da messaggio
che ho gia' postato. In ogni caso, faro' altri test utilizzando
entrambe le soluzioni. Grazie di tutto!
P.S. Ho visitato il tuo sito. Quest'argomento potrebbe essere
trattato in un ulteriore capitolo...
--
Massimo Fauro