• Regolamento Macrocategoria DEV
    Prima di aprire un topic nella Macrocategoria DEV, è bene leggerne il suo regolamento. Sei un'azienda o un hosting/provider? Qui sono anche contenute informazioni per collaborare con Sciax2 ed ottenere l'accredito nella nostra community!

Info Uso delle DLL in C++

KEKKOR97

Utente Strepitoso
Autore del topic
4 Luglio 2009
4.392
87
Miglior risposta
0
Una DLL, per definizione, è una libreria a caricamento dinamico (Dynamic Link Library ). In quanto libreria è un file che esporta dati, risorse e codice, visibili al programmatore nel momento in cui questi vengono importati.
Il caricamento effettivo degli elementi importati avviene sempre a runtime (tempo di esecuzione), in due modi fondamentali:

- il caricamento (loading) è effettuato prima di utilizzare la risorsa importata per la prima volta.

- il caricamento avviene subito dopo che la risorsa è stata importata, dunque all'avvio del programma

L'uso delle librerie dinamiche offre diversi vantaggi operativi. Si pensi ad una libreria di esempio che contenga la semplice funzione.

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Il codice efficiente che svolge il calcolo in questione è ben noto, e la funzione è di uso relativamente frequente. Senza utilizzare librerie, ogni programma che impiega la funzione dovrebbe contenere al suo interno il prototipo ed il codice in forma esplicita.
L'uso della libreria permette la semplice importazione del prototipo, mentre il codice sorgente che implementa la funzione è oscuro al programmatore (la libreria è un file compilato, analogamente al file eseguibile).
Saltano all'occhio diverse proprietà vantaggiose offerte dalle DLL: in primo luogo la modularità, un contenuto della libreria è indipendente da qualsiasi programma; si garantisce quindi la massima portabilità (qualunque programma può utilizzarla semplicemente importando le risorse offerte). Una DLL è importabile anche da un programma scritto con un linguaggio di programmazione diverso da quello con cui è stata complilata, si guadagna quindi in flessibilità.
Una DLL è sempre aggiornabile, se si riscontrano problemi nell'implementazione, errori o banalmente implementazioni migliori, si può riscrivere e ricompilare la sola libreria; per aggiornare ognuno dei programmi che la utilizzano sarà necessario sostituire il solo file DLL chiamato.

Le DLL sono librerie condivise; capita spesso che alcune funzioni molto frequenti, ad esempio le funzioni di sistema, siano richiamate da una parte rilevante di programmi. In questo caso si ha un notevole risparmio di spazio fisico perchè il codice importato è presente in memoria secondaria una sola volta. Senza librerie sarebbe stato obbligatorio avere una copia delle risorse per ognuno dei programmi utilizzatori.
Un programma può richiedere l'esecuzione di un servizio solo per una fase limitata del suo funzionamento. Il caricamento dinamico permette che una funzione di libreria sia caricata e rilasciata a tempo di esecuzione, in questo modo si può razionalizzare ed ottimizzare l'utilizzo delle risorse, in particolar modo nei casi più critici in cui si dispone di risorse limitate.
Infine si noti la protezione del codice: il fatto che la DLL sia compilata garantisce al programmatore la possibilità di diffondere il suo prodotto, ad esempio una funzione, facendo in modo che l'utilizzatore possa impiegarlo senza conoscere l'implementazione, che può essere quindi tenuta segreta.

Struttura di una DLL

Una DLL ha una struttura analoga ad un file eseguibile, suddivisibile in tre sezioni principali come esposto in figura.
Quando la libreria viene caricata è eseguito immediatamente il codice relativo all' Entry Point: la funzione DllMain (un file EXE ha come entry point la funzione Main).
Il resto del file è costituito da elementi esportati, comunemente funzioni, che il programmatore può importare direttamente ed indipendentemente dal programma principale.

cpp_dll.png


Contenuto di una DLL:

- L'Entry Point
In Win32 tutte le librerie di collegamento dinamico (DLL) possono contenere una funzione di punto di ingresso facoltativa, generalmente denominata DllMain, chiamata per inizializzazione e terminazione. Ciò consente l'opportunità di assegnare o rilasciare risorse aggiuntive secondo le necessità. Windows chiama la funzione di punto di ingresso in quattro situazioni: aggancio e disconnessione da un processo, connessione e disconnessione dai thread. (Ref:
Perfavore, Entra oppure Registrati per vedere i Link!
) Tramite il valore di un parametro (fdwReason) è possibile risalire a quale degli eventi citati ha scatenato l'attivazione dell'entry point.

- Variabili e funzioni esportate
Elementi il cui accesso è consentito ai processi e alle funzioni che importano la libreria. Si tende ad esportare soprattutto le funzioni.
Una DLL C++, se si usa l'ambiente VisualStudio, è esportata ed importata tramite le direttive __declspec(xxx), ma questo verrà visto nel dettaglio in seguito.

- Variabili e funzioni private
Elementi il cui accesso è consentito solo a membri interni alla stessa libreria. Solitamente le variabili di libreria sono private.

- Risorse Solitamente accodate alla fine del file, le risorse sono elementi di supporto all'applicazione come immagini, icone, video, e file html. Si includono all'interno del file compilato per mantenere una certa compattezza dell'applicazione (pochi file talvolta sono meglio di tanti file, specie nelle applicazioni semplici). Oltre questo si possono nascondere sotto la compilazione file che non si intende distribuire separatamente.
Non sono affatto rari i casi in cui la DLL è un file che contiene solo risorse (si pensi alle librerie di icone di sistema di Windows).

Ogni processo che utilizza la stessa DLL dispone di una propria copia delle variabili globali esportate.
Oltre questo fatto, di norma in una libreria è buona cosa che il codice sia condiviso in "read only" e che le variabili non siano condivise (questo implica l'esistenza di una copia delle variabili per ognuno dei processi utilizzatori).
Questo fatto non è obbligatorio; un programmatore con esigenze particolari può effettuare (a suo rischio) scelte differenti.

Esportazione di una DLL in Microsoft VisualStudio

All'interno di una DLL le funzioni esportate si distinguono dalla normali funzioni per via della specifica dichiarazione.
Il modo "standard" (proposto da Microsoft) per la semplice esportazione di una DLL prevede la creazione di una define condizionale come indicato nell'esempio.
Una volta creata la direttiva si possono dichiarare le variabili e le funzioni che si intendono esportare grazie alla stessa.

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

In VisualStudio, per indicare il tipo d'uso delle funzioni si usa la direttiva __declspec(dllexport), la quale non è standard C++.

Similarità e differenze tra DLL e applicazioni

Le DLL e le applicazioni hanno in comune tra loro il fatto che entrambi sono moduli eseguibili di un programma. Nonostante questo differiscono tecnicamente in vari aspetti. L'utente medio noterà senza dubbio la differenza più evidente: le DLL non sono programmi direttamente eseguibili mentre le applicazione EXE si.
Il sistema ed il programmatore invece osservano, oltre che certamente la prima, altre due differenze fondamentali:

- Un'applicazione può essere eseguita contemporaneamente in più istanze, una stessa libreria è istanziata una sola volta;

- Un'applicazione può contenere uno stack, una memoria globale, una coda di messaggi ed handle a file.

Creazione di una DLL in Microsoft VisualStudio

Una DLL come gia visto ha una struttura simile al file eseguibile. I contenuti (in sostanza codice e risorse) sono di tipo analogo.
Un progetto DLL, la cui creazione è possibile attraverso la voce di menù new avrà dunque un aspetto assolutamente simile al classico progetto di una normale applicazione.

A livello pratico , tralasciando la definizione delle risorse che tra l'altro è gestita per via grafica dall'IDE allo stesso modo dei progetti EXE, riporto un esempio sui principali elementi che i progetti DLL possono contenere:

Entry point:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Funzione generica esportata:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Funzione generica privata:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Importazione di una DLL in Microsoft VisualStudio

Una funzione di libreria si importa mediante la direttiva non standard __declspec(dllimport).

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

L'utilizzo di __declspec(dllimport) è facoltativo nelle dichiarazioni di funzioni, ma consente al compilatore di produrre un codice più efficiente. È necessario utilizzare __declspec(dllimport) per consentire all'eseguibile che importa di accedere agli oggetti e ai simboli pubblici della DLL.

Compilazione e caricamento di una DLL

La fase di compilazione di una DLL, la quale prevederebbe diversamente dal caso dei file eseguibili opzioni particolari del compilatore, è preconfigurata automaticamente in VisualStudio che sceglie le opzioni coerentemente col tipo di progetto con cui si lavora. La libreria compilata puo essere caricata in maniere diverse, in modo statico o dinamico.

Caricamento statico (implicito):

Il collegamento implicito a una DLL, prevede il possesso dei seguenti oggetti da parte del creatore del progetto che intende importare la libreria:

- La libreria vera e propria compilata (.DLL).

- Un file header (.h) contenente le dichiarazioni degli elementi esportati. Tutte le classi, le funzioni e i dati dovrebbero essere caratterizzati dalla direttiva: __declspec(dllimport).

- Una libreria di importazione, (.LIB), alla quale effettuare il link statico. Quando viene generata la DLL la libreria di importazione è creata dal linker.

Il programma che deve caricare la libreria lo fa in fase di creazione del processo.
Il file .LIB associato alla DLL è collegato al programma in modo statico. Le funzioni della DLL vengono rese disponibili all'interno del programma che carica la libreria mediante mapping automatico.
Caricamento dinamico (esplicito):

Le applicazioni devono effettuare una chiamata a funzione per caricare direttamente la DLL in fase di esecuzione.
La procedura standard consiste nel chiamare le seguenti funzioni in modo opportuno:

- LoadLibrary: Carica la DLL e permette di ottenere l'handle necessario a manipolare le risorse offerte dalla libreria.

- GetProcAddress: Restituisce un puntatore per ciascuna funzione esportata che l'applicazione intende chiamare. Poiché le applicazioni chiamano le funzioni della DLL tramite un puntatore, il compilatore non genera riferimenti esterni.

- FreeLibrary: Rilascia la risorsa impegnata dal sistema dopo avere terminato le operazioni relative alla DLL.

Condivisione dei dati

Il problema della condivisione dei dati tra processi che utilizzano la stessa libreria non può essere risolto banalmente dall'impiego di variabili globali. Infatti per default di queste ne è disponibile una copia per ogni processo che importa la libreria.
La soluzione potrebbe essere quella di allocare le variabili globali in un segmento di memoria condivisa, ma questo sistema pare contorto e poco flessibile per il programmatore.
Comunque ne illustriamo un semplice esempio:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Al fine di risolvere la stessa questione viene incontro un particolare tipo di oggetto kernel chiamato FileMapping, il quale viene dichiarato sovente nella funzione di EntryPoint.

L'istanziatore dedicato CreateFileMapping(...) esegue una creazione condizionale del seguente tipo:

- Se l'oggetto non è stato ancora creato lo alloca e ne restituisce l'handle.

- Se l'oggetto è stato gia creato viene semplicemente restituito l'handle

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Quando tutti i chiamanti la libreria rilasciano la stessa anche l'oggetto FileMapping è rilasciato.

Fonte: Mrwebmaster​
 
Riferimento: Uso delle DLL in C++

Scommetto che di quello che hai postato non ci hai capito nulla, e nemmeno io ho capito qualcosa, o meglio, qualcosa sì, ma non tutto. Non credi che sarebbe stato meglio informarsi prima e dare anche delle spiegazioni del codice ? Perchè non ha senso postare delle guide se poi non c'è la spiegazione.
 
Riferimento: Uso delle DLL in C++

Scommetto che di quello che hai postato non ci hai capito nulla, e nemmeno io ho capito qualcosa, o meglio, qualcosa sì, ma non tutto. Non credi che sarebbe stato meglio informarsi prima e dare anche delle spiegazioni del codice ? Perchè non ha senso postare delle guide se poi non c'è la spiegazione.
Il nesso credo sia quello, come usare le DLL.
 
Riferimento: Uso delle DLL in C++

Il nesso credo sia quello, come usare le DLL.

Quale nesso ?

Qui la questione è questa : un utente che non ha mai visto una riga di codice in C, vede questa discussione e si mette le mani ai capelli perchè non c'è spiegato nulla, sono solo codici.
 
Riferimento: Uso delle DLL in C++

Quale nesso ?

Qui la questione è questa : un utente che non ha mai visto una riga di codice in C, vede questa discussione e si mette le mani ai capelli perchè non c'è spiegato nulla, sono solo codici.
Ma infatti non scrivo info, guide etc. per utenti che non sanno niente. Se quei utenti che dici tu, vengono qui, vedono questa discussione e non ci capiscono niente, non è un mio problema se non hanno studiato la programmazione.
 
Riferimento: Uso delle DLL in C++

Una domanda, ma tu ci hai capito qualcosa di tutto ciò?Oltre che da fastidio leggere una cosa così lunga scritta come un poema di Manzoni.
Una domanda cos'è wchar e a cosa serve, come funziona?
 
Riferimento: Uso delle DLL in C++

Ma infatti non scrivo info, guide etc. per utenti che non sanno niente. Se quei utenti che dici tu, vengono qui, vedono questa discussione e non ci capiscono niente, non è un mio problema se non hanno studiato la programmazione.

A prescindere dal fatto che la guida non l'hai scritta tu e che hai fatto semplicemente copia/incolla, comunque, ti spiego come avviene la cosa : io ( utente che non ho mai visto una riga di codice ) vedo questa guida. Appena inizio a leggere mi metto le mani ai capelli, e allora qual'è la cosa che mi viene istintiva ? Quella di chiedere spiegazioni al "creatore" della guida, perchè TEORICAMENTE si presume che quando si scrive una guida, l'autore ne conosca i minimi particolari ( del contenuto ). Stessa cosa DOVREBBE avvenire quando si copia/incolla una guida ( almeno secondo il punto di vista, potrei anche sbagliarmi ), ma quello che voglio dire è questo : inutile postare guide di cui non si conosce il contenuto
 
Riferimento: Uso delle DLL in C++

Mi sà che non hai capito nulla come me e come gli altri scusa ma informati prima di postare è poi è una poesia di manzoni lòl comunque bravo per aver postato :emoji_slight_smile: