Abbiamo visto nella prima parte dell'articolo (vedete link nel box in fondo alla pagina), come costruire una DLL utilizzando Visual C++.
E' necessario ora completare il nostro discorso utilizzando la DLL in un progetto .NET e utilizzando la sua funzione che abbiamo costruito appositamente chiamata Somma.
Si comincia innanzitutto lanciando il nostro ambiente Visual Studio .NET e creando come al solito un nuovo progetto di tipo "Windows Application", in linguaggio C#.
Diamo il nome "CallDLL" al progetto.
Come indiciato precedentemente per poter utilizzare la funziona Somma, dovremo ricorrere ad una classe fornita dal Framework dal namespace System.Runtime.InteropServices.
Quindi come primo passo fra la lista dei namespace referenziati bisogna aggiungere la seguente riga:
using System.Runtime.InteropServices;
(Per accedere al codice è sufficiente fare click con il tasto destro sulla form e premere "View Code")
Come secondo passo, copiamo la DLL creata nell'articolo precedente nella cartella "Debug" o "Release" (dipende in che modalità stiamo lavorando) in modo che l'eseguibile possa vederla.
Per chi lo desidera, si può anche copiare la DLL nella cartella System32 della cartella di Windows, in questo modo sarà sicuramente visibile.
Siamo pronti per iniziare, ma prima una breve introduzione sul namespace InteropServices.
Che cosa è System.Runtime.InteropServices?Come segnalato nella prima parte dell'articolo, la maggior parte del codice in circolazione è ancora scritto con i linguaggi di vecchia generazione, e per migrare le applicazioni è necessario parecchio tempo e spesso non è così semplice.
Ricordiamo che molti dei componenti in circolazione sono componenti basati su tecnologia COM/COM+/DCOM, ActiveX ecc.
Era necessario poter richiamare questi oggetti/moduli dalle nuove applicazioni scritte in .NET. Ecco quindi il perchè di queste classi speciali, che infatti servono per poter operare con i "vecchi componenti", così come accedere alle API native.
Come potete vedere dalla documentazione del Framework questo namespace comprende veramente molte classi, cominciamo a vederne una molto importante.
DllImportAttributeTorniamo dove avevamo lasciato il discorso.
Visualizziamo nuovamente il codice dell'applicazione.
Dopo la definizione di classe aggiungiamo il seguente codice:
[DllImport("SumDll.dll")]
public static extern int Somma(int a,int b);
il risultato dovrebbe essere il seguente:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
namespace CallDLL
{
public class Form1 : System.Windows.Forms.Form
{
[DllImport("SumDll.dll")]
public static extern int Somma(int a,int b);
//Altro codice....
Bene, come vedete, utilizziamo DllImport per indicare al compilatore che stiamo importando una funzione dalla libreria SumDll.dll e di seguito troviamo il prototipo della funziona esportata.
In questo caso il tipo di dati int si rimappa correttamente con gli interi di C/C++.
Se avessimo avuto come parametri delle stringhe oppure delle strutture da noi create dovevamo anche ricorrere all'attributo MarshalAsAttribute per definire il Marshaling dei parametri.
Il Marshaling non è altro che il processo di mapping fra tipi di variabili managed e unmanaged e viceversa in modo da non creare ambiguità nelle chiamate. Ma il nostro obbiettivo è far comprendere in modo semplice come poter richiamare le funzioni di librerie esterne da .NET.
Compiling... Building... Running!Manca solo una riga di codice per poter testare la nostra applicazione: è la chiamata alla funziona appena definita.
Tasto destro sulla form e "View Code". L'ambiente ci posizionerà direttamente all'interno del metodo Load della nostra Form.
Aggiungiamo le seguenti righe di codice in modo da ottenre questo output:
private void Form1_Load(object sender, System.EventArgs e)
{
int a=12;
int b=48;
Console.WriteLine("Primo Addendo: " + a.ToString());
Console.WriteLine("Secondo Addendo: " + b.ToString());
Console.WriteLine("La somma è: " + Somma(a,b).ToString());
}
Il codice è sufficientemente facile da capire. Abbiamo definito le due variabili a e b di tipo int, abbiamo assegnato due valori arbitrari (12 per a, 48 per b), nelle righe seguenti visualizziamo a Console il primo addendo, il secondo, e la somma dei due utilizzando la nostra funzione.
Dal menù Debug selezionate Run.
La finestra di output dovrebbe mostrare il seguente risultato:
L'output durante l'esecuzione del programma
12+48=60! Semplice no?