PDA

View Full Version : Urgenza linguaggio C e dll


Fiat82
23-01-2007, 14:42
Ciao a tutti ho questo problema.
Sto scrivendo,usando il borland 5.5, un programma in C che deve utilizzare dei metodi dichiarati all'interno di una dll.
In mio possesso ho un file .dll e un file .lib di cui nn ne conosco l'origine ma sono sicuro che contengono i metodo che voglio usare nel mio progetto(mi sono creato il file. def della dll usando l'utility del borland impdef e ho verificato i metodi inseriti).
il file .lib è stato convertito usando coff2omf in modo da renderlo compatibile al Borland.
ho richiamato la dll all'interno del codice usando il comando LoadLibrary e passandoli come parametro il percorso dove trovare la dll.
il file .lib convertito è stato inserito nel percorso delle librerie del progetto.
Il problema è che l'oggetto di tipo HINSTANCE che dovrebbe permettere di accedere ai metodi contenuti nelle dll è sempre NULL come se nn vedesse la dll.
che devo fare?Grazie
:muro:

andbin
23-01-2007, 15:12
Ciao a tutti ho questo problema.
Sto scrivendo,usando il borland 5.5, un programma in C che deve utilizzare dei metodi dichiarati all'interno di una dll.
In mio possesso ho un file .dll e un file .lib di cui nn ne conosco l'origine ma sono sicuro che contengono i metodo che voglio usare nel mio progetto(mi sono creato il file. def della dll usando l'utility del borland impdef e ho verificato i metodi inseriti).
il file .lib è stato convertito usando coff2omf in modo da renderlo compatibile al Borland.
ho richiamato la dll all'interno del codice usando il comando LoadLibrary e passandoli come parametro il percorso dove trovare la dll.
il file .lib convertito è stato inserito nel percorso delle librerie del progetto.
Il problema è che l'oggetto di tipo HINSTANCE che dovrebbe permettere di accedere ai metodi contenuti nelle dll è sempre NULL come se nn vedesse la dll.
che devo fare?Grazie
:muro:Allora ... innanzitutto, almeno per mia esperienza personale, non sempre coff2omf riesce a convertire correttamente la lib. Mi sono capitati dei casi in cui non era riuscito a fare il suo dovere ...

Comunque la questione è che se riesci, in qualche modo, ad ottenere una "import library", non hai poi bisogno di usare LoadLibrary, perché linkando con la import library, il tuo eseguibile avrà una dipendenza "statica" verso la DLL.
Al contrario, se preferisci effettuare il caricamento della libreria a run-time con LoadLibrary (e GetProcAddress per ottenere l'indirizzo delle funzioni), non hai più bisogno della import library, ti basta solo sapere nome e prototipo della funzione.

Fiat82
23-01-2007, 15:30
Allora ... innanzitutto, almeno per mia esperienza personale, non sempre coff2omf riesce a convertire correttamente la lib. Mi sono capitati dei casi in cui non era riuscito a fare il suo dovere ...

Comunque la questione è che se riesci, in qualche modo, ad ottenere una "import library", non hai poi bisogno di usare LoadLibrary, perché linkando con la import library, il tuo eseguibile avrà una dipendenza "statica" verso la DLL.
Al contrario, se preferisci effettuare il caricamento della libreria a run-time con LoadLibrary (e GetProcAddress...per ottenere l'indirizzo delle funzioni), non hai più bisogno della import library, ti basta solo sapere nome e prototipo della funzione.
ciao, per prima cosa grazie di aver risposto.
Allora io vorrei usare il metodo con caricamento dinamico dei metodi(quindi LoadLibrary e GetProcAddress)il problema è che al momento di caricare la dll nn viene rilevata.
intanto seguo il tuo consiglio e tolgo dal library path il percorso del file .lib.
dimmi cosa devo fare per essere sicuro che la dll venga letta e perciò possa usare i metodi in essa contenuti.
grazie mille

andbin
23-01-2007, 15:40
Allora io vorrei usare il metodo con caricamento dinamico dei metodi(quindi LoadLibrary e GetProcAddress)Ok

il problema è che al momento di caricare la dll nn viene rilevata.
intanto seguo il tuo consiglio e tolgo dal library path il percorso del file .lib.
dimmi cosa devo fare per essere sicuro che la dll venga letta e perciò possa usare i metodi in essa contenuti.Innanzitutto la funzione LoadLibrary ricerca la DLL usando una sequenza ben precisa, riporto qui di seguito la sequenza (dalla documentazione ufficiale):
1) The directory from which the application loaded.
2) The current directory.
3) The system directory. Use the GetSystemDirectory function to get the path of this directory.
4) The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
Windows Me/98/95: This directory does not exist.

5) The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
6) The directories that are listed in the PATH environment variable.
Poi non saprei dirti di preciso cosa c'è che non va. Magari posta il codice, così vediamo se è corretto o meno.

Fiat82
23-01-2007, 15:49
Ok

Innanzitutto la funzione LoadLibrary ricerca la DLL usando una sequenza ben precisa, riporto qui di seguito la sequenza (dalla documentazione ufficiale):
Poi non saprei dirti di preciso cosa c'è che non va. Magari posta il codice, così vediamo se è corretto o meno.
hinstLibNomi=LoadLibrary("c:\prova.dll");//in questo percorso c'è la dll
poi passo a richiamare il metodi.
Il problema è che la variabile hinstLibNomi mi rimane nulla invece di essere valorizzata.
il mio dubbio è che se la dll nn fosse stata scritta in modo compatibile col borland come faccio a farla diventare?
il file .lib a cosa serve al borland?
parlo del . lib che mi ho ottenuto con implib o con coff2omf?

andbin
23-01-2007, 16:08
hinstLibNomi=LoadLibrary("c:\prova.dll");//in questo percorso c'è la dllSe proprio vuoi mettere un path assoluto, devi fare l'escape di \, quindi "c:\\prova.dll"

Comunque sconsiglierei di mettere un path assoluto (se non ci sono necessità particolari, ovviamente). Basta usare solo il nome della DLL. Poi è sufficiente che la DLL stia in PATH o nella stessa directory dell'eseguibile.

il mio dubbio è che se la dll nn fosse stata scritta in modo compatibile col borland come faccio a farla diventare?Normalmente è ininfluente con quale tool/compilatore è stata fatta la DLL. A te basta sapere il nome esatto (eventualmente decorato) della funzione e il prototipo esatto, che comprende anche il modo di passaggio degli argomenti.

il file .lib a cosa serve al borland?
parlo del . lib che mi ho ottenuto con implib o con coff2omf?È una "import library", una libreria che non contiene variabili o funzioni ma che serve solo per ottenere una dipendenza statica con una DLL.
I file .lib possono anche ovviamente contenere variabili/funzioni, in quel caso non sono import library ma librerie statiche "normali".

P.S. se vuoi vedere le funzioni esportate da un DLL, usa il tool Dependency Walker (http://www.dependencywalker.com).

Fiat82
23-01-2007, 16:15
Se proprio vuoi mettere un path assoluto, devi fare l'escape di \, quindi "c:\\prova.dll"

Comunque sconsiglierei di mettere un path assoluto (se non ci sono necessità particolari, ovviamente). Basta usare solo il nome della DLL. Poi è sufficiente che la DLL stia in PATH o nella stessa directory dell'eseguibile.

Normalmente è ininfluente con quale tool/compilatore è stata fatta la DLL. A te basta sapere il nome esatto (eventualmente decorato) della funzione e il prototipo esatto, che comprende anche il modo di passaggio degli argomenti.

È una "import library", una libreria che non contiene variabili o funzioni ma che serve solo per ottenere una dipendenza statica con una DLL.
I file .lib possono anche ovviamente contenere variabili/funzioni, in quel caso non sono import library ma librerie statiche "normali".

P.S. se vuoi vedere le funzioni esportate da un DLL, usa il tool Dependency Walker (http://www.dependencywalker.com).
si ho copiato male volevo scrivere hinstLibNomi=LoadLibrary("c:\\prova.dll");
ma il problema rimane come mai hinstLibNomi è nullo?
allora il file .lib originale che era insieme alla dll e il file .lib che mi sn creato non servono a nulla se seguo la strada del link dinamico?

andbin
23-01-2007, 16:21
si ho copiato male volevo scrivere hinstLibNomi=LoadLibrary("c:\\prova.dll");
ma il problema rimane come mai hinstLibNomi è nullo?Beh, non ne ho idea ... chiama GetLastError() e vedi che codice di errore indica.

allora il file .lib originale che era insieme alla dll e il file .lib che mi sn creato non servono a nulla se seguo la strada del link dinamico?Esatto.

Fiat82
23-01-2007, 16:25
Beh, non ne ho idea ... chiama GetLastError() e vedi che codice di errore indica.

Esatto.
mi dici cosa avrei dovuto fare se avessi usato i linker non dinamico ma statico?
grazie

andbin
23-01-2007, 16:38
mi dici cosa avrei dovuto fare se avessi usato i linker non dinamico ma statico?
grazieNon devi più usare LoadLibrary/GetProcAddress (ovviamente) e poi devi semplicemente specificare al linker di fare il link con la import library.
Per chiamare le funzioni hai però bisogno di sapere comunque i prototipi delle funzioni (questo per il compilatore).

Fino ad adesso hai parlato solo di un file .dll e un file .lib. In genere insieme a questi due, dovrebbe essere dato anche uno (o più) file di include (.h) che contiene le varie definizioni, prototipi, ecc... utili per usare la libreria.

Fiat82
23-01-2007, 16:48
Non devi più usare LoadLibrary/GetProcAddress (ovviamente) e poi devi semplicemente specificare al linker di fare il link con la import library.
Per chiamare le funzioni hai però bisogno di sapere comunque i prototipi delle funzioni (questo per il compilatore).

Fino ad adesso hai parlato solo di un file .dll e un file .lib. In genere insieme a questi due, dovrebbe essere dato anche uno (o più) file di include (.h) che contiene le varie definizioni, prototipi, ecc... utili per usare la libreria.
si ho anche un file.h che contiene le dichiarazioni extern ai metodi contenute nella dll.
devo controllare qc?
cq nn funziona nulla.nn riesco con entrambe le strade ad ottene qc

andbin
23-01-2007, 16:55
si ho anche un file.h che contiene le dichiarazioni extern ai metodi contenute nella dll.
devo controllare qc?Perfetto, devi semplicemente fare un #include di questo file .h nel tuo sorgente.

cq nn funziona nulla.nn riesco con entrambe le strade ad ottene qcPurtroppo non posso aiutarti più di tanto (la sfera di cristallo non ce l'ho ancora ;) ) .... per quanto riguarda il caricamento a runtime, hai provato a vedere cosa restituisce GetLastError() ?? Potrebbe essere utile.
Per quanto riguarda l'utilizzo della import library, quale è il problema?? In fase di link? quando avvii il programma??

Fiat82
23-01-2007, 16:58
Perfetto, devi semplicemente fare un #include di questo file .h nel tuo sorgente.

Purtroppo non posso aiutarti più di tanto (la sfera di cristallo non ce l'ho ancora ;) ) .... per quanto riguarda il caricamento a runtime, hai provato a vedere cosa restituisce GetLastError() ?? Potrebbe essere utile.
Per quanto riguarda l'utilizzo della import library, quale è il problema?? In fase di link? quando avvii il programma??
il mio problema è in fase di esecuzione, l'oggetto che rappresenta la dll è null e perciò nn riesco a richiamare i metodi.
GetLastError che cosa è?

andbin
23-01-2007, 17:04
GetLastError che cosa è?È una funzione Win32 che restituisce il codice di errore dell'ultima funzione chiamata.
if (hInstDLL == NULL)
{
CHAR szMsg[32];
wsprintf (szMsg, "Error %lu", GetLastError ());
MessageBox (NULL, szMsg, "LoadLibrary Failed", MB_OK);
}Così almeno sai che diavolo di errore è.

Fiat82
23-01-2007, 17:13
È una funzione Win32 che restituisce il codice di errore dell'ultima funzione chiamata.
if (hInstDLL == NULL)
{
CHAR szMsg[32];
wsprintf (szMsg, "Error %lu", GetLastError ());
MessageBox (NULL, szMsg, "LoadLibrary Failed", MB_OK);
}Così almeno sai che diavolo di errore è.
ultima cortesia mi sai dire dove trovo il significato dell'errore?a me esce errore 126 e basta

Fiat82
23-01-2007, 17:16
ultima cortesia mi sai dire dove trovo il significato dell'errore?a me esce errore 126 e basta
ho trovato
//
// MessageId: ERROR_MOD_NOT_FOUND
//
// MessageText:
//
// The specified module could not be found.
//
#define ERROR_MOD_NOT_FOUND 126L

in winerror.h

andbin
23-01-2007, 17:18
ultima cortesia mi sai dire dove trovo il significato dell'errore?a me esce errore 126 e bastaGli errori li trovi nell'include WinError.h, che fa parte degli include del Platform SDK.

L'errore 126 è ERROR_MOD_NOT_FOUND (The specified module could not be found)

71104
23-01-2007, 20:23
ultima cortesia mi sai dire dove trovo il significato dell'errore?a me esce errore 126 e basta si era già capito dal primo post :p
anche se il modulo è già caricato implicitamente tramite import, LoadLibrary restituisce sempre l'handle (la differenza tra LoadLibrary e GetModuleHandle è che la prima incrementa anche il reference count). quindi se non te l'ha restituito vuol dire che non trovava il file.

71104
23-01-2007, 20:25
una precisazione :p
Allora io vorrei usare il metodo con caricamento dinamico dei metodi (quindi LoadLibrary e GetProcAddress) quello si chiama esplicito, non dinamico. il caricamento di una DLL è sempre dinamico, altrimenti non si chiamerebbe Dynamic Linked Library :)

il linking statico invece è un'altra cosa.

71104
23-01-2007, 20:29
altra cosa: Visual C++ in edizione Enterprise include un utilissimo tool che spero non abbiano rimosso nella versione 2005 (non l'ho ancora provata in edizione Enterprise) che si chiama Error Lookup (ERRLOOK.EXE) e restituisce, dato il numero di un errore di sistema ritornato da GetLastError(), la stringa descrittiva dell'errore (vedere API FormatMessage).

Fiat82
24-01-2007, 08:19
si era già capito dal primo post :p
anche se il modulo è già caricato implicitamente tramite import, LoadLibrary restituisce sempre l'handle (la differenza tra LoadLibrary e GetModuleHandle è che la prima incrementa anche il reference count). quindi se non te l'ha restituito vuol dire che non trovava il file.
ciao il problema è che nel percorso specificato il file .dll esiste veramente come è possibile che nn lo veda?

Fiat82
24-01-2007, 08:43
ciao il problema è che nel percorso specificato il file .dll esiste veramente come è possibile che nn lo veda?
il problema è la dll se io lascio tutto il codice invariato e metto un altra dll di un vecchio progetto funziona tutto.
quindi il problema è la dll che mi hann passato che il bulider nn riesce a caricare.
che posso fare?

71104
24-01-2007, 15:01
il problema è la dll se io lascio tutto il codice invariato e metto un altra dll di un vecchio progetto funziona tutto.
quindi il problema è la dll che mi hann passato che il bulider nn riesce a caricare.
che posso fare? allora è chiaro: la DLL che non riesci a caricare ritorna FALSE dalla DllMain. hai i sorgenti?

71104
24-01-2007, 15:02
ciao il problema è che nel percorso specificato il file .dll esiste veramente come è possibile che nn lo veda? anche se il problema sembra essere la DLL, e non la chiamata a LoadLibrary, chiedo ugualmente per sicurezza: hai usato backslashes nel path (\), e non forward slashes (/) ?

Fiat82
24-01-2007, 15:14
anche se il problema sembra essere la DLL, e non la chiamata a LoadLibrary, chiedo ugualmente per sicurezza: hai usato backslashes nel path (\), e non forward slashes (/) ?
si ho usato \\ e non /.
Putroppo io nn ho i sorgenti ho solo la dll.cosa può essere?

71104
24-01-2007, 15:19
si ho usato \\ e non /.
Putroppo io nn ho i sorgenti ho solo la dll.cosa può essere? tutto e niente... se non hai i sorgenti cerca innanzitutto di capire cosa manca a quella DLL in base alle tue conoscenze sul suo funzionamento: ha bisogno di altre librerie che mancano? ha bisogno di girare sotto un account con privilegi particolari? ha bisogno di ritrovarsi files di inizializzazione che non trova? se la risposta a tutte e tre le domande è "non lo so" (:p) allora devi scoprirlo usando il Dependency Walker (http://www.dependencywalker.com/) per la prima e FileMon (http://www.microsoft.com/technet/sysinternals/FileAndDisk/Filemon.mspx) per le altre due. o più semplicemente chiedi a chi ha scritto quella DLL :p

Fiat82
24-01-2007, 17:49
tutto e niente... se non hai i sorgenti cerca innanzitutto di capire cosa manca a quella DLL in base alle tue conoscenze sul suo funzionamento: ha bisogno di altre librerie che mancano? ha bisogno di girare sotto un account con privilegi particolari? ha bisogno di ritrovarsi files di inizializzazione che non trova? se la risposta a tutte e tre le domande è "non lo so" (:p) allora devi scoprirlo usando il Dependency Walker (http://www.dependencywalker.com/) per la prima e FileMon (http://www.microsoft.com/technet/sysinternals/FileAndDisk/Filemon.mspx) per le altre due. o più semplicemente chiedi a chi ha scritto quella DLL :p
putroppo nn ho modo di contattare chi ha scritto la dll.
domanda, una dll per essere correttamente caricata nel borland deve avere qc caratteristica?può nn essere compatibile?ho modo di verificarlo?

Fiat82
24-01-2007, 17:56
tutto e niente... se non hai i sorgenti cerca innanzitutto di capire cosa manca a quella DLL in base alle tue conoscenze sul suo funzionamento: ha bisogno di altre librerie che mancano? ha bisogno di girare sotto un account con privilegi particolari? ha bisogno di ritrovarsi files di inizializzazione che non trova? se la risposta a tutte e tre le domande è "non lo so" (:p) allora devi scoprirlo usando il Dependency Walker (http://www.dependencywalker.com/) per la prima e FileMon (http://www.microsoft.com/technet/sysinternals/FileAndDisk/Filemon.mspx) per le altre due. o più semplicemente chiedi a chi ha scritto quella DLL :p
news quando arriva il punto in cui carico la dll mi viene fuori un errore in cui viene detto che un altra dll nn viene trovata....come può essere?

Fiat82
24-01-2007, 18:32
news quando arriva il punto in cui carico la dll mi viene fuori un errore in cui viene detto che un altra dll nn viene trovata....come può essere?
sistemato ho messo in visione tutte le dll che nn vedeva ma il problema principale rimane

71104
24-01-2007, 21:47
putroppo nn ho modo di contattare chi ha scritto la dll. in tal caso la cosa migliore è non usarla. in programmazione vale la regola che se non hai il supporto di qualcuno per fare una cosa è meglio che non la fai.
quella DLL cosa fa? puoi trovare qualche strumento sostitutivo?

domanda, una dll per essere correttamente caricata nel borland deve avere qc caratteristica?può nn essere compatibile? non che io sappia... BCB dovrebbe poter caricare qualsiasi DLL. sicuramente quella DLL ritorna FALSE dalla DllMain. che risultati hai ottenuto con FileMon?

Fiat82
29-01-2007, 09:31
tutto e niente... se non hai i sorgenti cerca innanzitutto di capire cosa manca a quella DLL in base alle tue conoscenze sul suo funzionamento: ha bisogno di altre librerie che mancano? ha bisogno di girare sotto un account con privilegi particolari? ha bisogno di ritrovarsi files di inizializzazione che non trova? se la risposta a tutte e tre le domande è "non lo so" (:p) allora devi scoprirlo usando il Dependency Walker (http://www.dependencywalker.com/) per la prima e FileMon (http://www.microsoft.com/technet/sysinternals/FileAndDisk/Filemon.mspx) per le altre due. o più semplicemente chiedi a chi ha scritto quella DLL :p
con il primo programma ottengo
Warning: At least one delay-load dependency module was not found.
Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.

ora passo al secondo programma.
Ma esattamente Dependency Walker che cosa mi dovrebbe dire?nel guardare le dll associate ne vedo tantissime che nn so dove le trova ma le trova

71104
29-01-2007, 16:13
lascia perdere i delay-load, il tuo problema avviene prima. ed inoltre è probabile che i moduli mancanti non siano quelli da cui dipende il tuo eseguibile (o la tua DLL). per quanto riguarda il numero di DLL, a te interessano solo quelle del primo livello gerarchico (le "figlie" dell'eseguibile principale), quindi chiudi la radice e riaprila, in modo che vengano mostrate solo quelle. tra quelle dovrebbe esserci la DLL che fa i capricci, espandila e vedi un po' che dipendenze ha: se qualcuno dei files da cui dipende non viene trovato il DW te lo segnala.

71104
29-01-2007, 16:15
ah, casomai allega uno screenshot del DW in cui si veda l'eseguibile principale espanso e tutti i "figli" chiusi tranne la DLL che fa i capricci.

Fiat82
30-01-2007, 08:28
lascia perdere i delay-load, il tuo problema avviene prima. ed inoltre è probabile che i moduli mancanti non siano quelli da cui dipende il tuo eseguibile (o la tua DLL). per quanto riguarda il numero di DLL, a te interessano solo quelle del primo livello gerarchico (le "figlie" dell'eseguibile principale), quindi chiudi la radice e riaprila, in modo che vengano mostrate solo quelle. tra quelle dovrebbe esserci la DLL che fa i capricci, espandila e vedi un po' che dipendenze ha: se qualcuno dei files da cui dipende non viene trovato il DW te lo segnala.
ma grazie a quel programma ho capito quale sono le dll che devono esserci perchè richiamati.
il problema è quando carico tale dll nell'applicazione che ho fatto col borland non ci riesce.
se ho una dll che al sua volta richiama altre dll devo fare qc di speciale nel borland?

71104
30-01-2007, 16:11
ma grazie a quel programma ho capito quale sono le dll che devono esserci perchè richiamati.
il problema è quando carico tale dll nell'applicazione che ho fatto col borland non ci riesce.
se ho una dll che al sua volta richiama altre dll devo fare qc di speciale nel borland? no, la famiglia di funzioni LoadLibrary carica automaticamente tutti i moduli nell'albero di dipendenze (o almeno ci prova, e se non ne trova qualcuno resitituisce errore). se ora sei assolutamente sicuro che tutte le DLL necessarie siano a... "distanza di caricamento" (:p), è giunto il momento di rianalizzare il valore restituito dalla GetLastError subito dopo la LoadLibrary. ma probabilmente si tratta ancora di qualche DllMain che esce con FALSE (cosa dice FileMon?).