Newsgroup: it.comp.programmare.win32
Titolo: Newbie - uso di una .dll

Salve.
Sono un niubbo della programmazione (conosco giusto le basi), ma per
motivi di lavoro mi trovo ad affrontare un problema abbastanza
complesso. Non ho purtroppo il tempo di mettermi a studiare tutto da
zero, quindi spero possiate darmi una mano a risolvere il problema.
Situazione: ho una scheda con sopra un FPGA. Sono in grado di
comunicare con l'FPGA tramite una porta USB2.0. Le persone che mi
hanno dato la board mi hanno anche fornito due file: SiUSBLib.dll e
SiUSBLib.h: secondo quanto mi dicono loro, dovrei usare questi file
per comunicare con l'FPGA via porta USB. Mi hanno inotlre spedito un
driver, che ho installato.
Sempre in accordo con quanto mi dicono loro, la .dll è stata scritta
"per Borland C++ Builder 6.0, ma può essere integrata in applicazioni
MSVC". il che vuol dire, per quel che capisco, che la posso usare
(cosa che sto facendo) con Visual C++ 2008 express edition.
A questo punto, devo scrivere un qualche tipo di codice e usare le
funzioni della .dll per lavorare con l'FPGA.
Lavorando con un amico, abbiamo raggiunto questo punto:
nell'header file, c'è questa struttura:
#ifdef CF__LINUX
 #define DECLDIR
#endif
#ifdef __VISUALC__
 #ifdef DLL_EXPORT
   #define DECLDIR __declspec(dllexport)
#elif USE_STATIC_LIB
 #define DECLDIR
#else
   #define DECLDIR __declspec(dllimport)
 #endif
#endif
Da quel che ho capito, questa struttura serve a definire
automaticamente DECLDIR, a seconda dell'ambiente in cui lavoro; per un
qualche tipo di ragione, questo non avviene automaticamente e devo
definire nel mio file test.cpp la seguente linea:
#define __VISUALC__
La risposta che ho ricevuto sull'altro NG è questa
This is needed to tell the header file what compiler you are using.
The DECLDIR magic is there to tell the compiler when to import or
export symbols from the dll. So far, so good.
Quindi, spero, dovrei riuscire a capire cosa succede, ora.
Dopodichè, definiamo questa roba:
typedef bool DECLDIR (*InitUSBFunc)();
che onestamente non mi è chiara. Presumo abbia a che fare con
quest'altra cosa che è definita nell'header file:
// USB device management functions
bool DECLDIR  InitUSB();
int  DECLDIR  GetNumberOfUSBBoards();
int  DECLDIR  GetMaxNumberOfUSBBoards();
void DECLDIR * GetUSBDevice(int Id, int DevClass = -1);
void DECLDIR * GetUSBDeviceIndexed(int index);
std::stringstream   DECLDIR *GetDevInfoString(int index);
Dopodichè, nel main, definiamo con i seguenti comandi come caricare la
libreria:
       HINSTANCE hinstlib;    //Handle to DLL.
       hinstlib = LoadLibrary(TEXT("SiUSBLib.dll"));
Ho trovato questi comandi in giro per il web; non posso dire che mi
sono totalmente chiari, ma credo di aver capito che in qualche modo
sta roba vuol dire "carica la .dll, in modo che io possa usare le
funzioni implementate nella .dll stessa".
A questo punto sono sicuro che la .dll sia caricata, perchè (a scopo
di debug) ho un ciclo if di questo tipo:
InitUSBFunc _initusb;
if (hinstlib != NULL) {
               printf("Library successfully LOADED\n");
}
A questo punto, voglio usare le funzioni nella .dll, ma non ho idea di
come fare. Ho provato qualcosa di questo tipo:
_initusb = (InitUSBFunc) GetProcAddress(hinstlib, "InitUSB");
Anche questo proviene dall'aver girato in parecchi siti web, ma non ho
chiaro cosa io stia cercando di ottenere con tale scrittura. Inoltre,
se scrivo qualcosa del tipo (sempre a scopo debug)
if (_initusb) {
                       printf("true\n");
               } else {
                       printf("false\n");
               }
Quello che ottengo è sempre "false" (la mia ipotesi è: ottengo false
se non connetto la board alla porta USB, ottengo true se la
connetto...ma ottengo sempre false)
Giusto per chiarezza, nell'header file ho:
class DECLDIR SiUSBDevice
{
public:
 SiUSBDevice(void * dev);
 ~SiUSBDevice();
       // update internal USB device pointer
       void SetDeviceHandle(void * dev);
//dopodichè, ci sono alcune funzioni (presumo)
// identification values
int         GetId();
const char* GetName();
int         GetClass();
 int         GetFWVersion();
//O altre come queste:
// FPGA access (via controller core)
bool WriteXilinx   (unsigned short address, unsigned char *Data, int
length = 1);
bool ReadXilinx    (unsigned short address, unsigned char *Data, int
length = 1);
// FPGA configuration
bool DownloadXilinx(const char *fileName);
.
.
.
.
Ora, capisco che la question è abbastanza aperta e non ben definita,
ma non riesco a chiedere niente di meno specifico di "potete per
favore darmi alcuni suggerimenti e spiegazioni di cosa sta succedendo
qui, e di come potrei fare per usare le funzioni e comunicare via
porta USB?" Ho cercato in giro cose riguardanti API, .dll e simili, ma
onestamente il livello è un pò troppo alto per me.
Aggiungo: a quanto pare, se avessi un .lib file le cose potrebbero
essere molto più semplici, e ho ricevuto anche qualche input in questa
direzione, per cui mi metterò a cercare anche in questo settore.
Intanto, grazie mille già solo per aver letto fin qua :D
ciao
Francesco.

 _initusb = (InitUSBFunc) GetProcAddress(hinstlib, "InitUSB");
E' probabile che non funzioni perch� le funzioni della DLL sono "decorate".
Anzich� InitUSB il simbolo potrebbe essere _InitUSB oppure _InitUSB@N, con
N uguale al numero di bytes passati nello stack (che tipicamente � uguale
al numero di parametri moltiplicato per quattro). Per sincerartene scarica
il programmino "dependency walker" (� gratis) che ti permette di
visualizzare tutte le funzioni esportate e importate da un eseguibile o
dll.
-- 
emboliaschizoide.splinder.com

 
<snip>...

prova con:
   char* initUSB = "_InitUSB";
   _initusb = (InitUSBFunc) GetProcAddress(hinstlib, initUSB + 1);
   if(!_initusb)
     _initusb = (InitUSBFunc) GetProcAddress(hinstlib, initUSB);
in pratica, prova anche con l'underscore davanti
Metto qui uno stralcio di codice per facilitare il caricamento
//------------------------------------------------------------------
template <typename T>
bool getProcAddress(HMODULE hdll, LPCSTR procName, T& proc)
{
   FARPROC f = GetProcAddress(hdll, procName + 1);
   if(!f)
     f = GetProcAddress(hdll, procName);
   if(!f)
     return false;
   proc = (T)f;
   return true;
}
//------------------------------------------------------------------
da usarsi:
if(getProcAddress(hinstlib, initUSB, _initusb))
   printf("success!");
else
   printf("failed!");
Ciao


wrote:
[cut]
Grazie ad entrambi per le risposte, darò un'occhiata e vedo se riesco
a ricavarne qualcosa di utile :D
ciao ciao
Konx.