2009-03-19 19 views
5

Ho letto this article e ho trovato il concetto di interfaccia di libreria virtuale piacevole per il caricamento in fase di esecuzione delle DLL. Tuttavia sembra che non siano disponibili per Win32. È vero? E se è così: perché? Non vedo cosa legherebbe l'idea a .NET.Interfacce libreria virtuale per Delphi/Win32?

EDIT: Per lo più sto riformulando ciò che Rob ha già scritto. :-)
Non uso i plugin o simili - si tratta di semplici vecchie DLL Win32. Ciò che mi attrae è l'idea di consentire al compilatore di gestire tutti i dettagli del caricamento di una DLL in fase di esecuzione - non è necessario chiamare GetProcAddress per ogni funzione nella DLL ecc.

risposta

6

Mi sembra che le tre risposte finora abbiano completamente ignorato il punto della domanda. Quello, o io ho. Stai chiedendo perché Win32 Delphi non ha qualcosa come la magica funzione Supports di cui parla l'articolo di Hallvard, vero? Vale a dire, una funzione che, dato il nome di una DLL e le informazioni sul tipo di un'interfaccia, restituisce un oggetto che implementa tale interfaccia utilizzando le funzioni indipendenti esportate dalla DLL.

Hydra sembra voler chiamare il codice .Net da un programma Win32, non l'importazione di funzioni da una DLL. TJvPluginManager richiede che le DLL dei plug-in esportino una funzione di autoregistrazione speciale che il gestore chiamerà quando carica la DLL e la funzione deve restituire un'istanza della classe TJvPlugin, quindi la DLL del plug-in deve essere scritta in Delphi o C++ Builder. La funzione Supports, d'altra parte, funziona con qualsiasi DLL scritta in qualsiasi lingua. Potresti usarlo su kernel32, se lo volessi.

Non so perché Win32 Delphi non ha una cosa del genere. Forse CodeGear non ha visto molta richiesta perché Delphi e Turbo Pascal se ne erano già andati così a lungo senza.

È sicuramente possibile scrivere una funzione che funzioni in questo modo, e non mi aspetto che sarebbe più difficile scrivere di quanto la versione .Net debba essere stata, a meno che le librerie .Net di Microsoft già forniscano la maggior parte dei pezzi e Delphi li avvolge semplicemente in una funzione conveniente da chiamare che assomiglia alle diverse altre versioni sovraccaricate di che Delphi ha avuto per anni.

Ci sarebbero alcuni passaggi per l'implementazione di quella funzione in Win32. (Sto fornendo solo uno schizzo di ciò che è necessario perché in questo momento non ho una copia di Delphi in esecuzione. Chiedi gentilmente, e forse troverò maggiori dettagli.) In primo luogo, dovresti assicurarti che quel tipo informazioni per un'interfaccia contenevano, come minimo, i nomi non decorati dei suoi metodi. Quindi, Supports dovrebbe generare una funzione stub per ogni metodo nell'interfaccia (oltre a _AddRef, _Release e QueryInterface). Lo stub sarebbe qualcosa di simile, assumendo la convenzione di chiamata stdcall:

asm 
    // Pop the return address, 
    // discard the "this" pointer, 
    // and restore the return address 
    pop eax 
    pop ecx 
    push eax 

    jmp AddressOfFunction 
end; 

Come Supports generato ogni stub, sarebbe riempire l'indirizzo reale funzione, ottenuto dalla chiamata GetProcAddress con il nome del metodo corrispondente interfaccia. La convenzione di chiamata stdcall è facile da avvolgere in questo modo; cdecl è un po 'macchinoso; register è un dolore al collo.

Una volta che tutti gli stub sono stati generati, avrebbe dovuto generare un "oggetto" che assomiglia all'implementazione dell'interfaccia fornita. Non deve essere una classe reale. Al momento della compilazione, Supports non conosce il layout dell'interfaccia che verrà chiesto di implementare, quindi avere una classe non sarebbe molto utile.

Il passaggio finale è fornire implementazioni di _AddRef, _Release e QueryInterface. _AddRef sarebbe irrilevante; _Release è dove si chiamerebbe FreeLibrary quando il conteggio dei riferimenti ha raggiunto lo zero; QueryInterface non farebbe molto, ad eccezione del fatto che supporta IUnknown e l'interfaccia fornita a Supports.

Delphi era solito venire con un programma di esempio che dimostrava l'implementazione di un'interfaccia senza alcuna classe. Tutto è stato fatto con i record e i puntatori di funzione (che in fin dei conti è un'interfaccia, dopotutto). Delphi è arrivato anche con il codice corrispondente per farlo con le classi, in parte per mostrare quanto più facile Delphi può fare le cose. Non riesco a trovare il nome del programma demo ora, ma sono sicuro che sia ancora in giro da qualche parte.

+0

L'ho affrontato brevemente nella mia risposta. Questa è la roba da "brutto scherzo in giro con i puntatori" in cui non volevo entrare. Oh, e come bonus laterale, comporta anche brutti muck in giro in assemblea. Ho dimenticato quella parte! : P –

+0

In realtà, non il montaggio. Codice macchina. L'assemblea che ho scritto sopra è solo a scopo illustrativo. Dovresti inserire il codice macchina direttamente perché genereresti il ​​codice in fase di esecuzione e non è disponibile un assemblatore di runtime. –

+0

+1, risposta ponderata e con una bella spiegazione dei dettagli tecnici. Grazie per aver trovato il tempo per scriverlo. – mghie

3

Esistono un numero di opzioni Win32 per questo tipo di funzionalità. Project JEDI ha un sistema di plugin open source come parte di JVCL che carica DLL o pacchetti e può includere moduli e quant'altro come funzionalità aggiuntiva.

Sono disponibili anche numerosi prodotti commerciali, tra cui lo TMS Plugin Framework e lo RemObjects Hydra.

1

Questo non è niente di nuovo o speciale. L'articolo parla solo di plugin. Il codice nativo è stato in grado di fare plugin per anni. L'unica cosa speciale di P/Invoke è che consente al codice nativo e a .NET di comunicare tra loro in un sistema di plugin, e il piccolo trucco in cui "la DLL può essere vista come un oggetto singleton che implementa l'interfaccia [così che] è possibile utilizzare la funzione Supporta dall'unità Borland.Delphi.Win32 per verificare se sono disponibili la DLL e tutti i metodi. "

Se si desidera eseguire l'articolo di Delphi per Win32, consultare le funzioni API LoadLibrary, GetProcAddress e FreeLibrary di Windows. Se devi assolutamente avere un'interfaccia come l'articolo descrive, devi scrivere tu stesso, sia nella DLL (se hai scritto tu stesso la DLL) scrivendo una funzione esportata che restituisce un'interfaccia, o nell'app chiamante, scrivendo un funzione che utilizza GetProcAddress per creare un'interfaccia dinamicamente. (Attenzione: questo richiede di solito più problemi di quanto non ne valga.)

La tua migliore scommessa è probabilmente solo per fare ciò che Tim Sullivan ha menzionato: usa TJvPluginManager dal JEDI VCL se hai solo bisogno del codice nativo, o Hydra se si deve parlare con assembly .NET.

0

Ho usato Hydra da solo per una soluzione Delphi (cioè non ho un'interfaccia con .NET) e funziona perfettamente anche per questo. E 'più facile da usare e aggiunge alcune sottigliezze, ma penso che è fondamentalmente implementato allo stesso modo il quadro plug-in "roll-your-own" che è ben descritto in questo articolo: http://www.saxon.co.uk/SinglePkg/

vorrei cercare un framework di plugin basato sull'interfaccia (come Hydra e il sistema "roll-your-own" nel paragrafo precedente), piuttosto che uno che semplicemente invia messaggi tra le app.

C'è un quadro plug Delphi su sourceforge, non so se è la stessa come nel progetto JEDI o no: http://sourceforge.net/projects/rd-dpf

Ci sono anche un paio di altre soluzioni commerciali, uno dei quali è DragonSoft di: http://www.dragonsoft.us/products_dsps.php

0

Cosa c'è di sbagliato nel fare ciò con semplici oggetti COM? Dichiarare un'interfaccia semplice che tutti i plug-in implementano e richiedere che ogni oggetto com includa una funzione esportata che restituisce la guida della classe. Quindi usare i "plug-in" è semplice come camminare attraverso la directory dei plugin alla ricerca di DLL che espongano la funzione di registrazione speciale, invocandola e quindi usando la classe guid per poi richiamare l'oggetto com.

Ho usato qualcosa di simile in un'applicazione commerciale WIN32 con grande successo. Il vantaggio era che potevo cambiare i plugin in entrata e in uscita a piacimento (a patto che l'applicazione non fosse in esecuzione per rimuovere quelli esistenti), la magia era tutta nell'interfaccia che ognuno di essi implementava.

+0

Questo è fondamentalmente il modo in cui TJvPluginManager funziona sotto il cofano, tranne che ha altri trucchi invece di COM. –

+0

Le DLL le cui funzioni si desidera chiamare non esporranno necessariamente alcun oggetto COM. Sono davvero confuso: da dove vengono tutti gli altri a pensare che Ulrich stia chiedendo dei plug-in !? –

+0

La funzione non esporta l'oggetto com, restituisce solo il comando necessario per accedere all'istanza dell'oggetto com nella dll. Sì, i suoi plugin, questo è il punto. Aggiungendo funzionalità in fase di runtime e binding tardivo, si suona sicuramente come se fosse richiesto un plug-in per l'architettura. – skamradt

Problemi correlati