Newsgroup: it.comp.programmare.win32
Titolo: Maledette DLL!!! export problem!

Ciao,
allora, sto creando questa benedetta dll servendomi
di un oggetto globale, ma interno alla stessa, in modo
da creare delle semplici funzioni di interfaccia che internamente
manipolano l'oggetto globale.
Ho creato il tutto, ma per prova, ho esportato una semplice funzione
che non ha nulla a che fare con l'oggetto, ma richiama solo una 
MessageBox: la compilazione va a buon fine!
In visual basic, tramite declare stile API, riesco ad eseguire la funzione.
In VisualC (questa volta per totale compatibilità, TUTTO è sviluppato 
con VisualC), includo la .lib, ma quando chiamo la funzione, mi da 
errore il linker:
Linking...
bla.obj : error LNK2001: unresolved external symbol "void __cdecl 
Messaggio(void)" (?Messaggio@@YAXXZ)
bla.exe: fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
Allora ho pensato, mah magari ci manca il prototipo di funzione, e 
quindi ho inserito in cima la dichiarazione, ma sempre uguale!

 Messaggio(void)" (?Messaggio@@YAXXZ)
Vedi la mia risposta precedente.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 
Grazie per la risposta: l'ho vista e letta...adesso vedi la mia 
precedente :-)

 __cdecl Messaggio(void)" (?Messaggio@@YAXXZ)
Questo dovresti risolverlo con un file di definizioni. Cioč crea 
un file .def ed inseriscilo nel progetto (della libreria). Il 
file, basilarmente, va composto come segue:
LIBRARY  NomeLibreria
EXPORTS
    NomeFunzione1    @1
    NomeFunzione2    @2
A questo punto le funzioni dovrebbero essere esportate col nome 
specificato. Ovvio che nel modulo che richiama la funzione il 
prototipo deve esserci.
Steve. 

 
Sob...sono demoralizzato!
Ho creato il file .def cosě come lo hai scritto tu, e oltre a darmi 
sempre lo stesso errore (il nome della funzione ancora codificato con 
C++), mi da:
exp : warning LNK4070: /OUT:bla.DLL directive in .EXP differs from 
output filename "Debug/bla.exe"; ignoring directive
warning LNK4086: entrypoint "_mainCRTStartup" is not __stdcall with 12 
bytes of arguments; image may not run
error LNK2001: unresolved external symbol "void __cdecl Messaggio(void)" 
(?Messaggio@@YAXXZ)
bla.exe: fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

 precedente :-)
allora, 2 cose:
1) sei sicuro di aver usato __cdecl in entrambe le dichiarazioni della
funzione? (cioè sia nella DLL che nell'EXE che la importa)
2) se per l'EXE puoi scegliere VC++ allora perchè non fai una prova di
importazione della classe stessa? non vedo quale problema potrebbe esserci
se il compilatore è lo stesso...


 Messaggio(void)" (?Messaggio@@YAXXZ)
Qui francamente non ti so aiutare, sembra quasi che il .def sia 
ignorato. Magari con uno stralcio di codice sarebbe più facile. 
Non mi hai ancora tolto la curiosità di prima però: perchè 
utilizzare due ambienti differenti e non fare tutto con BCB ad 
esempio?
Steve. 

 esempio?
stavolta dice che ha usato solo VC++


 se il compilatore è lo stesso...
Quindi se la esporto la posso utilizzare normalmente, come una normale
classe?!?

 stavolta dice che ha usato solo VC++
Sì, ho visto, ma volevo capire la scelta di prima.
Steve. 

 
Semplicemente perchč il restante progetto (il programma) senza
il codice della DLL, lo avevo creato con VC!!

>Messaggio(void)" (?Messaggio@@YAXXZ)
E questo č l'errore! :-(
La codifica in C č fatta bene perchč da VB dichiaro la funzione
con il suo nome (Messaggio) e la esegue benissimo!
Stesso vale per VC usando perň le API (LoadLibrary, ecc...)

>>Messaggio(void)" (?Messaggio@@YAXXZ)
L'errore potrebbe essere sensato allora. Come ti è già stato 
suggerito, prova con la seguente dichiarazione:
void __declspec(dllimport) Messaggio(void);
(nella libreria invece __declspec(dllexport)).
Steve. 

 void __declspec(dllimport) Messaggio(void);
Già lo avevo provato...ma questa dichiarazione è
utilizzata per il CBuilder che pretende tutte le
dichiarazioni da importare dalla DLL. In VC++, dovrebbe
bastare il file .lib
error LNK2001: unresolved external symbol "__declspec(dllimport) void 
__cdecl Messaggio(void)" (__imp_?Messaggio@@YAXXZ)

 (__imp_?Messaggio@@YAXXZ)
Mi sembra evidente che la funzione Messaggio non viene esportata 
con quel nome, oppure non hai detto al linker dove trovarla. 
Secondo me ricadi in uno dei casi ben descritti al seguente 
link:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/lnk2001.asp
Prova a vedere se c'è un punto che corrisponde alla tua 
situazione, io con le informazioni che hai dato non saprei 
cos'altro dire...
Steve. 

 
Il problema non è che manca il prototipo (te l'avrebbe detto il 
compilatore, non il linker).
Se in VB l'hai importata con un nome "non decorato" (senza il @@YA...) 
mi viene il sospetto che la funzione sia implementata in un file .c e 
richiamata in un c++ (che, in fase di link, cerca il nome decorato).
Per ovviare al problema devi inserire un blocco:
extern "C"
{
}
Attorno alla dichiarazione della funzione (nel .h).
-- 
Valter Minute
vmi...@inwind.it
 (the reply address of this message is invalid)

 cos'altro dire...
Grazie tante!
Ormai sto cedendo...ultima chicca che mi sta facendo pensare di prendere
i prodotti microsoft e buttarli nel cesso, è la seguente:
Uso le declare da VB, esporto le funzioni, e quando le chiama mi da 
l'errore: "Convenzione di chiamata DLL non valida"
ok, controllo che i parametri siano corretti nel tipo e nel numero, e nulla!
Allora, solita funzioncina Messaggio("testo da visualizzare"), la eseguo
ehhhh.....mi visualizza il messaggio, e quando clicco su ok, di nuovo lo
stesso errrore!!! araaaaaaaaaarrrrrrhhhghghhh!
Ho provato a togliere il tipo di ritorno, ma nulla...ditemi che non sono
diventato scemo io?!?

 Per ovviare al problema devi inserire un blocco:
mi spiace, ma nessun file con estensione .c viene utilizzato: tutti .cpp

 diventato scemo io?!?
Sembra che il mio compilatore accetta solo funzioni che non prendono 
parametri e non restituiscono parametri!!!
Togliendo il parametro della funzione, mi funziona correttamente!
Ma che sta succedendo!?!?

 wrote in
news:d8urqf$tme$
2...@newsreader.mailgate.org
: 

Come viene esportata la funzione?
Usi un declspec o passi per il file .def?
Con che nome la importi da VB?


 Con che nome la importi da VB?
Public declare Sub Messaggio lib "bla.dll" (byval messaggio as string)

 Ma che sta succedendo!?!?
mamma mia, ma guarda che io la prima volta che da una DLL di Visual C++ ho
importato una funzione in un programma Visual C++ mi ha funzionato tutto
senza problemi!!! non ho mica "buttato al cesso" i prodotti Microsoft!! :)
allora, fai cosě: chiudi Visual C++, riaprilo, crea un nuovo progetto (una
DLL Win32), aggiungici un file C e scrivici il seguente codice:
[CODE]
#include <windows.h>
__declspec(dllexport) int __stdcall FunzioneProva(LPCTSTR pszMsg) {
    return MessageBox(NULL, pszMsg, TEXT("prova"), 0);
}
[/CODE]
builda e chiudi (la DllMain mi sembra che non sia necessaria, sennň
metticene una fittizia).
poi fai un nuovo progetto (applicazione Win32), aggiungici un file C e
scrivici quest'altro codice:
[CODE]
#include <windows.h>
__declspec(dllimport) int __stcdall FunzioneProva(LPCTSTR pszMsg);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, int nShowCmd) {
    FunzioneProva(TEXT("ciao!"));
    return 0;
}
[/CODE]
poi includi il lib, builda pure questo, copia la DLL nella cartella di
questo progetto ed eseguilo. se non ti funziona manco cosě non so proprio
che dirti...


 classe?!?
si, secondo me non dovresti avere problemi (quando mai si è sentito che da
Visual C++ non riesci ad importare un simbolo di una DLL creata con Visual
C++?!?), basta che la dichiarazione della classe sia identica sia nell'EXE
che nella DLL (in genere si usa lo stesso header).


 [/CODE]
Allora dopo diverse prove, sono riuscito a far funzionare la libreria
nel progetto...in pratica, ho dovuto mettere extern "C" anche 
nell'importazione! Questo funziona (nel programma):
extern "C" __declspec(dllimport) Messaggio(char *msg);
Ma resta sempre il problema che in VB se passo un parametro qualsiasi,
come la stessa funzione su, mi da sempre errore (riguarda i parametri!).
E' mai possibile che non funzioni correttamente?!?!

 E' mai possibile che non funzioni correttamente?!?!
allora si tratta sicuramente di calling convention :)
esportala con __stdcall anziché __cdecl


 esportala con __stdcall anziché __cdecl
O dio mio!!!
Non ricordo di aver mai avuto tanti problemi nel far funzionare una DLL!!!
Se imposto (nella DLL e nel programma) __sdtcall, mi da (nel programma)
il seguente errore:
unresolved external symbol __imp__bla@8
unresolved external symbol __imp__bla_seconda@8
A parte che devo impostare il main cmq con _cdecl.
In VB (con le impostazioni standard _cdecl) se disattivo la gestione 
degli errori, cmq le funzioni svolgono il loro lavoro!!!
Ma come č possibile tutto questo?!?

 Ma come è possibile tutto questo?!?
Mentre la stessa dll nel programma VC, mi dice, all'avvio del prog, che 
non riesce a trovare il punto di ingresso nella dll per quella funzione!!!

 AlterX wrote:


a dire il vero tutti sti problemi non mi sono mai capitati (sarà
fortuna...)
comunque senti un attimo: tu hai fatto per filo e per segno quello che ti
dicevo di fare qualche post fa? due nuovi progetti (NUOVI!!) e scrivi quel
codice che ti ho scritto; un semplice esperimento di
esportazione/importazione che dovrebbe funzionare senza NESSUNISSIMO
problema (a meno che non abbia commesso io qualche banalità nel codice che
ti ho scritto, ma non mi sembra).
una volta fatto quello fai un esperimento di esportazione/importazione di
una classe anziché di una funzione; procedi nel seg. modo:
1) i due programmini che ti ho scritto sono C, quindi l'estensione che
dovresti aver messo ai due files è .c; cambiala in .cpp
2) aggiungi nella DLL una classe vuota e dichiarala come
__declspec(dllexport)
3) aggiungi la stessa classe nell'EXE e dichiarala come
__declspec(dllimport); le dichiarazioni delle due classi devono essere
rigorosamente IDENTICHE!!! (a parte il __declspec(dllxxx) naturalmente)
4) prova ad aggiungere qualche membro alla classe: un paio di funzioni e
di variabili pubbliche (e anche private, va'); le modifiche che fai nella
dichiarazione della classe nella DLL devono essere ESATTAMENTE LE STESSE
che fai nell'EXE.
segui questi passi e tra l'uno e l'altro fai sempre una prova di
compilazione per controllare che tutto funzioni (non fare semplici Build,
fai proprio Rebuild All per sicurezza); in tutto questo NON USARE Viual
Basic. se questi esperimenti ti riusciranno tutti senza problemi,
probabilmente ti aiuteranno a capire dov'è il problema nell'altro
programma (o nell'altra DLL).
facci sapere :)
ciao


 
No allora, c'č stato un piccolo disguido. Praticamente a casa funzionava 
e in ufficio no, perchč sul computer dell'ufficio avevo una versione 
della dll in system32 e quindi veniva chiamata quest'ultima, anzicchč
quella creata nella dir locale.
Come ho detto adesso in VC la dll funziona bene, ma resta sempre il 
fatto che la stessa dll in VB genera errore di convenzione, che se 
ignorato con On Error Resume Next, (le funzioni) fanno il loro compito!!