2012-02-13 12 views
6

Ho aggiunto questi due metodi alla prima unità della mia applicazione Delphi 5.Delphi può usare solo un file .dll se necessario?

function Inp(PortAddress: Integer): Integer; stdcall; external 'inpout32.dll' name 'Inp32'; 

procedure Output(PortAddress, Value: Integer); stdcall; external 'inpout32.dll' name 'Out32'; 

Tuttavia, non voglio dover rilasciare la libreria inpout32 con il software a meno che non ne abbia esplicitamente bisogno. Attualmente il programma dice "Not Found" all'esecuzione a meno che non siano presenti nella root o System32.

Gli utenti chiameranno questi metodi solo se hanno una specifica opzione impostata, ma questo non viene raccolto dal file .ini fino a quando non viene utilizzata la libreria di inpout.

C'è un modo per utilizzare questa libreria solo quando richiesto, come alcuni componenti, piuttosto che dichiararlo come ho?

+3

Sì, si può fare 'caricamento dinamico'. Usa 'LoadLibrary' e' GetProcAddress', come discusso [qui] (http://en.wikipedia.org/wiki/Dynamic_loading#Windows). –

risposta

15

Nelle versioni di Delphi precedenti al 2010, è necessario utilizzare il caricamento dinamico classico. Considerate questo tipico (e semplice) esempio chiamando la funzione Beep da Kernel32.dll (che si dovrebbe non hardcode il percorso nel codice reale, ovviamente!):

type 
    TBeepFunc = function(dwFreq: DWORD; dwDuration: DWORD): BOOL; stdcall; 

procedure TForm4.FormClick(Sender: TObject); 
var 
    lib: HMODULE; 
    prc: TBeepFunc; 
begin 

    lib := LoadLibrary('C:\WINDOWS\System32\Kernel32.dll'); 
    if lib = 0 then RaiseLastOSError; 
    try 
    @prc := GetProcAddress(lib, 'Beep'); 
    if Assigned(prc) then 
     prc(400, 2000) 
    else 
     ShowMessage('WTF? No Beep in Kernel32.dll?!'); 
    finally 
    FreeLibrary(lib); 
    end; 
end; 
+6

+1 per il messaggio !! ((: – ComputerSaysNo

+0

Grazie a @Andreas questa sembra la soluzione più semplice.La RaiseLastOSError non è stata riconosciuta nel mio Delphi 5. Sono sicuro di rimuovere l'istruzione If in quanto l'errore sarà sempre catturato dal secondo messaggio "WTF? libreria non caricata ?! " – notidaho

+1

@notidaho: No, se' lib = 0' non devi inserire il blocco 'try'. Puoi sostituire' RaiseLastOSError' con qualsiasi codice di eccezione, come 'raise Exception.Create (' Impossibile caricare la libreria. ') '. Ovviamente, puoi anche sostituire la riga in questoin con' if lib <> 0 then', in modo che l'intero 'try..finally..end' venga eseguito solo se il 'lib' è valida. Ma è probabilmente meglio per visualizzare un messaggio di errore –

16

Questa funzione, nota come delay loading, è stato aggiunto in Delphi 2010.

Utilizzando il codice di esempio si potrebbe scrivere l'importazione in questo modo:

function Inp(PortAddress: Integer): Integer; stdcall; 
    external 'inpout32.dll' name 'Inp32' delayed; 

Il legame a questa funzione esterna sarà eseguito solo quando viene chiamata la funzione per la prima volta. Se l'associazione fallisce, viene generata un'eccezione in fase di runtime.

È possibile utilizzare SetDliNotifyHook e SetDliFailureHook per personalizzare il comportamento di caricamento ritardato nel caso in cui sia necessario un controllo ancora più preciso.

Alcuni articoli del blog per integrare la documentazione del prodotto:


su versioni precedenti di Delphi è possibile utilizzare LoadLibrary e GetProcAddress. Oppure, se vuoi qualcosa di un po 'più delicato, posso raccomandare vivamente la classe di carico di ritardo di Hallvard Vassbotn che descrive come in this blog article. Questo codice avvolge tutta la piastra della caldaia della chiamata LoadLibrary e GetProcAddress ed è solo leggermente più ingombrante da utilizzare rispetto alla nuova funzione integrata Delphi 2010.

Ho usato con successo la libreria di Hallvard per molti anni. Una piccola parola di cautela è che non è protetto da thread, quindi se più thread tentano di collegarsi a una funzione nello stesso momento, il codice può fallire. Questo è abbastanza facile da risolvere aggiungendo blocchi interni al codice di Hallvard.

+0

Oh, quindi non c'è bisogno di 'GetProcAddress' e tutto il resto? Peccato, è stato divertente ... –

+1

@Andreas Personalmente sto ancora utilizzando GetProcAddress e la mia classe per gestire il caricamento ritardato, ma no, hanno aggiunto questa nuova funzionalità in D2010. Troppo tardi per te, temo. –

+0

Grazie David sembra una buona idea, ma c'è un modo per farlo in Delphi5? – notidaho

Problemi correlati