Using Pascal Libraries with .NET and Mono/ja
English (en) |
italiano (it) |
日本語 (ja)
はじめに
Microsoft 社は、"アンマネージドコード(unmanaged code)" と非常に互換性のある.NET framework を提供しています。アンマネージドコードというと何か野蛮で危険なもののように聞こえますが、これはネイティブの Windows ライブラリの書式の"レガシー"なコードのことをいいます。Mono プロジェクトには Linux と MacOS X のネイティブライブラリに対して(.NET と)同様のサポートが含まれています。これは Free Pascal でコンパイルしたライブラリを Windows の .NET アプリケーションや Linux や Mac OS X の Mono のアプリケーションから使えることを意味します。
シンプルな Pascal ライブラリ
次のPascalコードをコピーして 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.
Mac OS X (DARWIN)上でコンパイルした場合、条件付きの指示に注意して下さい。どうも OS X ダイナミックリンカーは アンダースコアから始まるライブラリのエントリーポイントを探そうとするようです。
ここで Free Pascal でライブラリをコンパイルします:
fpc -Sd SimpleLib.pas
Windows 上では、simplelib.dll というファイルを作成します。MacOS X 上では、libsimplelib.dylib というファイルを作成します。Linux 上では、simplelib.so というファイルを作成します。MacOS X や Linux では、コンパイルしたライブラリファイルを simplelib.dll にリネームします:
mv libsimplelib.dylib simplelib.dll
シンプルな VB.NET アプリケーション
次の VB.NET コードを 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
もし Windows 上に .NET framework をインストールしているのなら、次のようにすればコードをコンパイルできます:
[pathto]vbc TestLib.vb
[pathto] は .NET framework (.NET 1.1 での例: c:\windows\microsoft.net\framework\v1.1.4322\ ) へのパスです。これで TestLib.exe というファイルが作成されます。
もし Mono をインストールしてれば、同じように次の手順でコードをコンパイルすることができます:
mbas TestLib.vb
今のところ、Mono の VB.NET コンパイラはアルファ版の段階で、このコードはコンパイルできないかもしれません。もしコンパイルエラーが出たら、C# バージョンでコンパイルしてみて下さい。
シンプルな C# アプリケーション
ここにはC#互換のコードがあります。これを 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); } } }
.NET を使って次の方法でコンパイルできます。
[pathto]csc TestLib.cs
Mono を使って次の方法でコンパイルできます。
mcs TestLib.cs
.NET、Monoのどちらであっても、TestLib.exe というファイルが作成されます。
シンプルなアプリケーションの実行
.NETでは、コンパイルしたアプリケーションを実行方法は次の通りです。
testlib
.NET でライブラリを見つけられたら、アプリケーションはコンソール上に次の出力を行ないます:
Value is 123 Successor is 124 Predecessor is 122
Mono であれば、次のように実行します:
mono TestLib.exe
この際、Mono は simplelib.dll ファイルを探します --これが、上の Linux と Mac OS X 環境でライブラリ名を変更するように述べた理由です。
.NET/Mono の ".exe" ファイルは、実際にはネイティブコードを含んではいません。その代わり、.NET/Mono のランタイムによって実行されるバイトコードを含んでいます。その結果、Windows 上で作成した .NET の実行ファイルを、Mono を使ってリコンパイルすることなく Mac OS X や Linux 上で動かすことができるようになります(その逆も同様です)。
サポートを使用としてるプラットホーム用の Pascal ライブラリについてはリコンパイルする必要があります。
.Net/Mono からネイティブライブラリを使用する
なぜ、全てのコードを VB.NET や C# にしないのでしょうか?それは状況によって、それが最善ではない場合があるからです:
- C# で書き直し(もしくは再デバッグ)したくないような巨大で完全な Pascal コードを持っている場合
- ネイティブアプリケーション、.NET/Monoアプリケーションの両方から必要とされるネイティブライブラリを持っている場合
- パフォーマンス上の理由がある場合(たいていの場合、 FPC や Delphi でコンパイルされたネイティブコードは .NET/Mono 上で動作する同じ内容のバイトコードに比べて速く動きます)
- .NET/Mono では簡単にアタッチできないようなローレベルの処理システムが必要な場合
- 多人数開発の .NET/Mono プロジェクトのために、習熟している言語による開発コードがすぐに必要な場合
Mono tips
1. Visual Basic は Linux や MacOS X からするとかなり異質ですので、C++(Object Pascal)によく似たC#で .NET や mono アプリケーションの開発をしたくなると思います。
2. Mac OS X の Mono はアンインストール用のスクリプトを含んでいます。新しいバージョンの Mono をインストールする際は、予めアンインストール用のスクリプトを実行してください:
- ファインダーで /Library/Receipts を開きます
- MonoFramework.pkg の上で Ctrl を押しながらマウスをクリックします。ポップアップメニュー上で必要なパッケージを選択します。
- Contents フォルダをダブルクリックします。
- Resources フォルダをダブルクリックします。
- uninstallMono.sh をドラッグしてデスクトップにコピーします。
- ターミナルを開きます。
- cd desktop でデスクトップにカレントディレクトリを移します。
- sudo ./uninstallMono.sh を実行します。パスワードを聞かれたら入力します。
3. 通常、あなたが作成したライブラリの中で Lazarus のユニットを使用しないでください。通常、ライブラリはユーザインタフェースを含んではいけません。System、SysUtils、StrUtils、DateUtils、Classes、Variants、Math のような Free Pascal のユニットに止めておいて下さい。
4. もし、作成するライブラリでどうしてもインターフェースが必要なら、Windows フォームアプリケーションとしてそれをプログラムして下さい。ここに簡単な例があります。これをコピーして MyForm.cs というファイル名で保存します。
using System.Windows.Forms; public class MyForm: Form { public static void Main() { MyForm aForm = new MyForm(); aForm.Width = 350; Button b = new Button(); b.Left = 15; b.Top = 20; b.Width = aForm.Width-30; b.Height = 30; b.Text = "A Button"; aForm.Controls.Add(b); aForm.Text = "A .NET/Mono Windows Forms App"; Application.Run(aForm); } }
これを次のようにして、Mono でコンパイルします:
mcs -r:System.Windows.Forms MyForm.cs
次のようにして実行します:
mono MyForm.exe
Mac OS X 上では、Lazarus の実行がそうであるように、現バージョンの Mono も X11 を要求するので、 プログラムを実行するためには X11 ウィンドウ(ターミナルウィンドウではなく)を開いておく必要があります。
5. もし .NET や Mono から Pascal ライブラリを使用することに関して質問やコメントがあれば、Lazarus フォーラムにそれを投稿してください。