Tech Note 05: NS Basic/Palmで共有ライブラリを使う April 23, 2002
© NSB Corporation. All rights reserved. |
NS Basic/PalmはPalm OS共有ライブラリ(Shared Libraries)にアクセスすることが出来ます。このテクニカルノートでは共有ライブラリのプロシージャのロードとコールの基礎を説明します。
戻り値を持つ共有ライブラリのプロシージャは外部ファンクション(external function)とよび、戻り値を持たないものは外部サブ(external sub)と呼びます。
Information File (.inf)を使用することにより、NS Basic/Palmから共有ライブラリにアクセスすることができます。これらのファイルはNS Basic/Palmのサブディレクトリ「Lib」(ie. C:\NSBasic\Lib\*.inf)に納められています。共有ライブラリを使用するには、NS Basic/Palmの新しいキーワード「LoadLibrary」を使って、最初にプログラムにライブラリをロードしなければなりません。
シンタックス: LoadLibrary filename[, refname] 説明: filenameはLibディレクトリ内にある「.inf」拡張子をもつファイルです。 (.inf拡張子を付けるかは任意です) refnameはオプションの変数名で、後に 続く外部プロシージャのコールで、ライブラリを参照するために使用されます。 LoadLibraryをProject Startup Code(プロジェクト始動コード)から呼ぶこ とによりプロジェクトのどこからでもライブラリにアクセスすることが可能に なります。 例: (NS Basic/Palm IDE) LoadLibrary "Mathlib" 'Mathlib.infを使用, refname = mathlib LoadLibrary "Shortlib.inf" 'Shortlib.infを使用, refname = shortlib LoadLibrary "newlib", "nl" 'Newlib.infを使用, refname = nl
LoadLibraryは1つのコードオブジェクトを作成します。これは関連する共有ライブラリにある外部プロシージャにアクセスするのに使用されます。
シンタックス: refname.sub [arg1[, ar2...]] 'external sub foo = refname.function[(arg1[, arg2...])] 'external function 説明: refnameはLoadLibraryを呼ぶことによって作成されるコードオブジェクトです。 subとfunctionはプロシージャ名で関連する.infファイル内で説明されます。 例: (NS Basic/Palm IDE) foo = mathlib.sin( 0.5 ) shortlib.beep 3 nl.Backlight 1
共有ライブラリでルーチンを呼ぶ時、正しい変数タイプを使うことが重要です。呼ぶ側は変数タイプを使って、共有ライブラリに渡されるスタックに、値を入れます。共有ライブラリは、渡される各変数は正しいデータタイプであることを想定しています。
DIMステートメントを使って、使用する変数を宣言することによってこれを行います。リテラルを使用する場合、NS Basic/Palmは特定のデータタイプであると想定します。それらは、
小数点がない数値 | 63 | Int32 |
小数点がある数値 | 1.5 | Double |
文字列 | "Hello" | Char * |
計算式 | (1/2) | Float |
NS Basic/Palmで使用する共有ライブラリを作成することは、Palm OS用の共有ライブラリを作成するのと同じようなものです。共有ライブラリはCodeWarriorまたはGNUコンパイラなどを使用することにより作成できるでしょう。NS Basic/Palmでは共有ライブラリを作成することは出来ません。共有ライブラリの作成は、 http://oasis.palm.com/dev/kb/papers/1670.cfmKnowledge Baseの記事(英語)を参考にして下さい。共有ライブラリをNS Basic/Palmで動作させるには、外部プロシージャの引数および戻り値のタイプに注意を払って下さい。全ての引数および戻り値はchar*、int、またはdoubleでなければなりません。全てのプロシージャは、実行が成功したかを示すために、エラーコード(Err)を戻すようにします。Basicに値を戻すプロシージャ(ファンクション)は、戻り値へのポインターを最後のパラメータとして受けるようにします。この方法で、ファンクションはBasicへ1つだけ値を戻すことができます。
Examples: (CodeWarrior or GNU) Err Sin( double dblAngle, double *retVal ) '引数dblAngle, 戻り値*retVal Err Beep( int intBeepType ) '引数intBeepType, 戻り値なし Err Backlight( int intBacklightOn ) '引数intBacklightOn, 戻り値なし
一旦共有ライブラリが書かれ、デバッグも済み、正常に動作するようになったら、残るは適切なInformation Fileを書くだけです。.infはテキストファイルで以下のフォーマットを持っています。
; セミコロン (;) で始まるラインはコメントで、無視されます。 ; ; GENERAL PROPERTIES ; ; 全てのエクステンションは [General] セクションを持っています。いくつかのキーはオプションです。 ; ; ExtensionName: エクステンションのユーザ変数名(必須) ; PrcName: エクステンションの.PRCファイル名(必須) ; Version: エクステンションのバージョン(文字を含むことができる)(必須) ; Manufacturer: エクステンションの作成者(必須) ; =HelpStart= このキーはエクステンションのプロパティにあるヘルプテキストの始まりを ; 示します。各ラインをダブルクオーテーション(引用符)で囲んで下さい。 ; =HelpEnd= このキーでヘルプセクションを終わります。 ; (オプション、 default = "ヘルプは有効でない") [General] ExtensionName=Short_Library PrcName=ShortLib.prc Version=1.0 Beta Manufacturer=NSBasic.com ; ; EXTENSION HELP ; =HelpStart= "" "Short_Library is a simple shared library developed by nsbasic.com" "The library doesn't really exist, but is used for a demonstration" "in this Tech Note." "" =HelpEnd= ; ; METHOD PROPERTIES ; ; このセクションは以下のように構成されています: ; ; section: [GlobalMethods] ; name=index, type, numparams, helpstring ; ; 各キーは: ; ; name: メソッド名 ; index: ファンクションのインデックス。インデックスはevaluation stack上の最初のパラメータとして渡される。 ; type: "func" または "sub"。 Funcはインタプリタのevaluation stackに戻り値を入れるメソッド。 ; Subは戻り値を入れないメソッド。 ; numparams: メソッドで必要なパラメータ数。 ; helpstring: メソッドについての解説テキスト。(オプション) ; ; [GlobalMethods] beep= 1, sub, 1, "beep x" add2ints= 2, func, 2, "x = y + z"
ライブラリに関する追記事項は=HelpStart= と =HelpEnd=の間に含むことができます。各ルーチンを説明するこの追記事項とhelpstringはNS Basic/Palm IDEから参照出来ます。一貫性を持たせる為に、戻り値がないプロシージャは'sub'か'proc'に、戻りがあるプロシージャは'func'にすると良いでしょう。
他のInformation Fileの例として、mathlib.inf(下記)があります。これはNS Basic/Palmと共に配付されているパブリックドメインのmathライブラリを説明しています。既に存在する多くの共有ライブラリも、適切な.infファイルが書かれ、Libディレクトリに保管されていれば、NS Basic/Palmで使用が可能です。
フリーウエアのPRC-Tooksと共にコンパイルされたNS Basicの共有ライブラリのソースコードをご覧になるにはTech Note 18を参照して下さい。
Mathlibのソースコードはhttp://www.radiks.net/~rhuebner/mathlib.htmlから入手可能です。
; ; GENERAL PROPERTIES ; ; 全てのエクステンションは [General] セクションを持っています。いくつかのキーはオプションです。 ; ; ExtensionName: エクステンションのユーザ変数名(必須) ; PrcName: エクステンションの.PRCファイル名(必須) ; Version: エクステンションのバージョン(文字を含むことができる)(必須) ; Manufacturer: エクステンションの作成者(必須) ; =HelpStart= このキーはエクステンションのプロパティにあるヘルプテキストの始まりを ; 示します。各ラインをダブルクオーテーション(引用符)で囲んで下さい。 ; =HelpEnd= このキーでヘルプセクションを終わります。 ; (オプション、 default = "ヘルプは有効でない") ; [General] ExtensionName=SF-Math-Library PrcName=MathLib.prc Version=1.0 Beta Manufacturer=Clipage.com Inc. ; ; EXTENSION HELP ; =HelpStart= "" "SF-Math-Library is a Math plug-in developped by clipage.com" "The library can perform most Logarithmic and Algebraeic functions." "" "Note: "This Beta version of SF-Math-Library perform calls to the" "Palm MathLib that is a freeware program, and therefore you must only" "use this version with MathLib.prc. The Full version is a stand alone prc" "" "The Library has 43 methods:" "" "42 global methods that do calculation" "" """About"" is a private method that displays information about the" "extension in a dialog box." "" =HelpEnd= ; ; CONTROL PROPERTIES ; ; フォームに挿入可能なエクステンションは[Control]セクションを持たなければ ; なりません。ほとんどのキーはオプションです。 ; ; BaseName: App Designerでのコントロールの最初の部分 ; (例えば、"foo "はコントロール名"foo 1", "foo 2", etc ...を使う) (必須) ; ; InitialHeight: フォーム上のコントロールの初期高さ(オプション) ; InitialWidth: フォーム上のコントロールの初期幅(オプション) ; ResizableX: X方向にコントロールがサイズ変更可能かを示す(オプション、 default=1) ; ResizableY: Y方向にコントロールがサイズ変更可能かを示す(オプション、 default=1) ; ControlBitmap: App Designerに表示するコントロールを示すビットマップの名前(オプション、 default=none) ; BitmapAlign: コントロールビットマップのアライメント(整列)(オプション、 default=0) ; 0 = 左上コーナー ; 1 = 左下コーナー ; 2 = コントロールの枠にフィットさせる ; RequireDSource: コントロールがデータソースを必要とするかを示す ; (コントロールプロパティに現れるドロップリスト)(オプション、 default=0) ; AllowedTypes: データソースに許容されるデータタイプを指定する ; 複数のデータタイプを指定するには、値をORする(足す)(オプション、 default=3) ; 1 = character(文字) ; 2 = numeric(数値) ; 4 = logical(論理) ; 8 = date(日付け) ; 16 = time(時刻) ; 32 = ink(NS Basic/Palm では利用できない) ; ; [Control] セクションはありません。これはコントロールではなくplug-inです。 ; ; METHOD PROPERTIES ; ; スクリプトから使えるメソッドを提供するエクステンションは [????Methods] セクションを持つべきです。 ; これは2つのセクション、 [GlobalMethods] と [PrivateMethods] があります。これらの2つのセクションは ; 同じキーワードを使います。唯一の違いは、[GlobalMethods]のメソッドはグローバルな形でアクセスでき(それら ; の名前を使うだけ)、[PrivateMethods]は所有するオブジェクトを先に指定しなければなりません。このセク ; ションは以下のように複数のラインで構成されます。 ; ; name: index,type,numparams,helpstring ; ; 各キーは: ; ; name: メソッド名 ; index: ファンクションのインデックス。インデックスは最初のパラメータとしてevaluation stackに渡されます。 ; GlobalとPrivateメソッドはインデックスを共有するので、違うメソッドに同じインデックスを使用しないで下さい。 ; type: "func" または "proc"。 Funcはインタプリタのevaluation stackに戻り値を入れるメソッド。 ; Subは戻り値を入れないメソッド。 ; numparams: メソッドで必要なパラメータ数。変数の引数リストに、引数なしには-1、引数1つには-2、・・・ ; を使って下さい。 ; helpstring: メソッドについての解説テキスト。 ; ; ; メソッドはコントロール名を使った形で呼べます。 ; ; MyControl.my_method(param1, param2, ...) ; [GlobalMethods] acos= 1, func, 1, "acos(x)" asin= 2, func, 1, "asin(x)" atan= 3, func, 1, "atan(x)" atan2= 4, func, 2, cos= 5, func, 1, "cos(x)" sin= 6, func, 1, "sin(x)" tan= 7, func, 1, "tan(x)" sincos= 8, func, 1, "sincos(x)" cosh= 9, func, 1, "cosh(x)" sinh= 10, func, 1, "sinh(x)" tanh= 11, func, 1, "tanh(x)" acosh= 12, func, 1, "acosh(x)" asinh= 13, func, 1, "asinh(x)" atanh= 14, func, 1, "atanh(x)" exp= 15, func, 1, "exp(x)" frexp= 16, func, 1, "frexp(x)" ldexp= 17, func, 1, "ldexp(x)" ln= 18, func, 1, "ln(x)" log10= 19, func, 1, "log10(x)" modf= 20, func, 1, "modf(x)" expm1= 21, func, 1, "expm1(x)" log1p= 22, func, 1, "log(1+x)" logb= 23, func, 1, "Base 2 signed integral exponent of x" log2= 24, func, 1, "Base 2 logarithm of x" pow= 25, func, 2, "x to the y power [x**y]" sqrt= 26, func, 1, "Square root of x [x**0.5]" hypot= 27, func, 2, "sqrt(x*x + y*y) [hypotenuse of right triangle]" cbrt= 28, func, 1, "Cube root of x [x**(1/3)]" ceil= 29, func, 1, "Smallest integral value not less than x" fabs= 30, func, 1, "Absolute value of x" floor= 31, func, 1, "Largest integral value not greater than x" fmod= 32, func, 2, "Modulo remainder of x/y" isinf= 33, func, 1, "Return 0 if x is finite or NaN, +1 if +Infinity, or -1 if -Infinity" finite= 34, func, 1, "Return nonzero if x is finite and not NaN" scalbn= 35, func, 2, "x * pow(2,exponent)" drem= 36, func, 2, "Remainder of x/y" significand= 37, func, 1, "Fractional part of x after dividing out ilogb(x)" copysign= 38, func, 2, "Return x with its sign changed to match y's" isnan= 39, func, 1, "Return nonzero if x is NaN (Not a Number)" ilogb= 40, func, 1, "Binary exponent of non-zero x" rint= 41, func, 1, "Integral value nearest x in direction of prevailing rounding mode" nextafter= 42, func, 2, "Next machine double value after x in the direction towards y" remainder= 43, func, 2, "Remainder of integer division x/y with infinite precision" scalb= 44, func, 2, "x * pow(2,exponent)" round= 45, func, 1, "Round x to nearest integral value away from zero" trunc= 46, func, 1, "Round x to nearest integral value not larger than x" signbit= 47, func, 1, "Get the sign of x" [PrivateMethods] About= 0, proc, 0, "Show extension's about box."