Difference between revisions of "Using Pascal Libraries with .NET and Mono/it"
Line 229: | Line 229: | ||
Perché non scrivere semplicemente tutto il codice in VB.NET o C#? Ci sono diverse situazioni in cui questa può non essere una buona idea: | Perché non scrivere semplicemente tutto il codice in VB.NET o C#? Ci sono diverse situazioni in cui questa può non essere una buona idea: | ||
− | * | + | * quando si ha un lungo o complesso codice Pascal che non si vuole riscrivere (e ricorreggere) in C#; |
− | * | + | * quando si hanno librerie native che devono essere utilizzate da apps sia native, sia .NET/Mono; |
− | * | + | * quando ci sono motivi di prestazioni (presumilmente codice compilato in FPC o Delphi è più veloce di quello equivalente compilato sotto .NET/Mono); |
− | * | + | * quando è necessario un accesso a basso livello al sistema operativo, non facilmente disponibile con .NET/Mono; |
− | * | + | * quando è necessario sviluppare codice velocemente in un linguaggio che you're more proficient in for a multi-developer .NET/Mono project. |
== Appunti Mono == | == Appunti Mono == |
Revision as of 22:51, 4 April 2010
English (en) |
italiano (it) |
日本語 (ja)
Introduzione
Con .NET framework, Microsoft ha fornito una eccellente compatibilità per il codice "unmanaged" (non gestito). Se il termine "codice non gestito" sembra evocare qualcosa di selvaggio e pericoloso, esso rappresenta solo il cosiddetto codice "legacy" nella forma delle lbrerie native di Windows. Il progetto Mono comprende un analogo supporto per le librerie native di Linux e OS X. Questo significa che si possono compilare librerie con Free Pascal e usarle con applicazioni .NET in Windows e con applicazioni Mono in Linux e OS X.
Una semplice libreria Pascal
Copiare e salvare il seguente codice Pascal nel file SimpleLib.pas:
library SimpleLib; function MySucc(AVal : Int64) : Int64; stdcall; begin Result := System.Succ(AVal); end; function MyPred(AVal : Int64) : Int64; stdcall; begin Result := System.Pred(AVal); end; exports {$IFDEF DARWIN} {OS X entry points} MySucc name '_MySucc', MyPred name '_MyPred', {$ENDIF} MySucc, MyPred; end.
Notare la direttiva condizionale per compilazione su OS X (DARWIN). Apparentemente il linker dinamico di OS X cerca un punto d'ingresso alla libreria che inizi con un underscore.
Ora compilare la libreria con Free Pascal:
fpc -Sd SimpleLib.pas
In Windows, verrà creato il file simplelib.dll. In OS X, verrà creato il file libsimplelib.dylib. In Linux, this will create file simplelib.so. On OS X and Linux, rename the compiled library file to simplelib.dll:
mv libsimplelib.dylib simplelib.dll
Una semplice app VB.NET
Copare e salvare questo codice VB.NET nel file TestLib.vb:
Imports System Imports System.Runtime.InteropServices Public Class TestLib Const SimpLibName = "simplelib.dll" 'Declare external functions using the DllImport attribute. <DllImport(SimpLibName, EntryPoint:="MySucc", _ CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function Succ(ByVal AVal As Long) As Long End Function <DllImport(SimpLibName, EntryPoint:="MyPred", _ CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function Pred(ByVal AVal As Long) As Long End Function Public Shared Sub Main() Dim TestVal As Long Try TestVal = 123 Console.WriteLine("Value is " & TestVal) Console.WriteLine("Successor is " & Succ(TestVal)) Console.WriteLine("Predecessor is " & Pred(TestVal)) Catch e As Exception Console.WriteLine(e) End Try End Sub 'Main End Class 'TestLib
Se .NET framework è installato in Windows, si può compilare il codice così:
[pathto]vbc TestLib.vb
dove [pathto] è il percorso di .NET framework (example: c:\windows\microsoft.net\framework\v1.1.4322\ with .NET 1.1). Verrà creato il file TestLib.exe.
Se Mono è installato, si può anche provare a compilare il codice così:
vbnc TestLib.vb
Si può anche provare a compilare la versione C#:
Una semplice app C#
Questo è l'equivalente codice per C#. Copiarlo e salvarlo nel file TestLib.cs.
using System; using System.Runtime.InteropServices; public class TestLib { const string SimpLibName = "simplelib.dll"; //Declare external functions using the DllImport attribute. [DllImport(SimpLibName, EntryPoint="MySucc", CallingConvention=CallingConvention.StdCall)] public static extern long Succ(long AVal); [DllImport(SimpLibName, EntryPoint="MyPred", CallingConvention=CallingConvention.StdCall)] public static extern long Pred(long AVal); public static void Main() { long TestVal; try { TestVal = 123; Console.WriteLine("Value is " + TestVal); Console.WriteLine("Successor is " + Succ(TestVal)); Console.WriteLine("Predecessor is " + Pred(TestVal)); } catch(Exception e) { Console.WriteLine(e); } } }
Con .NET, si può compilarlo così:
[pathto]csc TestLib.cs
Con Mono, si può compilarlo così:
mcs TestLib.cs
Con .NET e Mono, la compilazione creerà il file TestLib.exe.
Una semplice app Pascal utilizzando Oxygene
Copiae e salvare il seguente codice Pascal nel file TestLib.pas:
namespace TestLib; interface uses System.Runtime.InteropServices; const SimpleLibName = 'simplelib.dll'; type TestLib = class private [DllImportAttribute(SimpleLibName, EntryPoint:='MySucc', CallingConvention:=CallingConvention.StdCall)] class method Succ(AVal : Int64) : Int64; external; [DllImportAttribute(SimpleLibName, EntryPoint:='MyPred', CallingConvention:=CallingConvention.StdCall)] class method Pred(AVal : Int64) : Int64; external; public class method Main; end; implementation class method TestLib.Main; var TestVal : Int64; begin try TestVal := 123; Console.WriteLine('Value is ' + TestVal); Console.WriteLine('Successor is ' + Succ(TestVal)); Console.WriteLine('Predecessor is ' + Pred(TestVal)); except on E: Exception do Console.WriteLine(E.Message); end; end; end.
Il compilatore free Oxygene Object Pascal è disponbile qui RemObjects Software.
Con .NET e Mono, si può compilare TestLib.pas così:
[pathto]oxygene TestLib.pas
Con .NET e Mono, verrà creato il file testlib.exe.
Eseguire la semplice app
Con .NET, eseguire la app compilata così:
testlib
Se .NET trova simplelib.dll, l'output nella console sarà:
Value is 123 Successor is 124 Predecessor is 122
Con Mono, eseguire la app compilata così:
mono TestLib.exe
Mono cercherà anche il file simplelib.dll -- e questo è il motivo per cui è stata rinominata la libreria compilata in Linux e OS X.
Notare che i files ".exe" di .NET/Mono non contengono codice compilato nativo. Invece, contengono bytecode eseguito da .NET/Mono a runtime. Come risultato, si può prendere un file .NET .exe creato in Windows ed eseguirlo con Mono su OS X e Linux (e viceversa) senza ricompilarlo. Si dovrà ricompilare le librerie Pascal su ogni piattforma che si vuole supportare.
Quando usare librerie native con .NET/Mono
Perché non scrivere semplicemente tutto il codice in VB.NET o C#? Ci sono diverse situazioni in cui questa può non essere una buona idea:
- quando si ha un lungo o complesso codice Pascal che non si vuole riscrivere (e ricorreggere) in C#;
- quando si hanno librerie native che devono essere utilizzate da apps sia native, sia .NET/Mono;
- quando ci sono motivi di prestazioni (presumilmente codice compilato in FPC o Delphi è più veloce di quello equivalente compilato sotto .NET/Mono);
- quando è necessario un accesso a basso livello al sistema operativo, non facilmente disponibile con .NET/Mono;
- quando è necessario sviluppare codice velocemente in un linguaggio che you're more proficient in for a multi-developer .NET/Mono project.
Appunti Mono
1. Poiché Visual Basic è un perfetto sconosciuto a Linux e OS X, probabilmente si vorrà sviluppare apps .NET e Mono utilizzando C#, che è simile a C++ (e Object Pascal). O usare il compilatore Oxygene e sviluppare apps .NET e Mono con un Object Pascal familiare.
2. Mono in OS X comprende uno script per la disinstallazione. E' bene eseguire questo script prima di installare una nuova versione di Mono:
- In Finder, navigate fino a /Library/Receipts.
- Ctrl+click su MonoFramework.pkg e scegliere Show Package Contents dal menu popup.
- Doppio-click su Contents folder.
- Doppio-click su Resources folder.
- Trascinare una copia di uninstallMono.sh sul desktop.
- Aprire una finestra Terminal.
- cd desktop
- sudo ./uninstallMono.sh e inserire la password.
3. In general, don't use any Lazarus units in your libraries. Libraries usually don't have a user interface. Confine your use to Free Pascal units like System, SysUtils, StrUtils, DateUtils, Classes, Variants and Math.
4. If you need a user interface to go with your library, program it as a Windows Forms application. Here's a simple form example. Copy and save this code to file MyForm.cs.
using System; using System.Windows.Forms; public class MyForm: Form { public MyForm () { this.Text = "A .NET/Mono Windows Forms App"; this.Width = 400; Button b = new Button(); b.Left = 15; b.Top = 20; b.Width = this.Width-30; b.Height = 30; b.Text = "Click Me"; b.Click += new EventHandler(button_Click); this.Controls.Add(b); } void button_Click(object sender, EventArgs e) { MessageBox.Show("Hello"); } } public class MyApp { public static void Main() { MyForm aForm = new MyForm(); Application.Run(aForm); } }
Compile this code on Mono as follows:
mcs -r:System.Windows.Forms MyForm.cs
Run the app as follows:
mono MyForm.exe
On OS X, you can also create a normal app bundle using the macpack utility:
macpack -n MyForm -m winforms MyForm.exe
This creates the MyForm.app bundle, which can be double-clicked, dropped onto the Dock, etc.
5. On Linux and OS X, Mono now includes MonoDevelop, a simple IDE for editing and compiling code.
6. If you have any questions or comments about using Pascal libraries with .NET or Mono, please post them to the Lazarus forum.