ctypes.jsm
コードモジュールは機能性の強化のために API 改訂中です。よってこの文書はそれが完了した際に改訂されるでしょう。ctypes.jsm
JavaScript コードモジュールは、自前のバイナリ XPCOM コンポーネントを書くことなく JavaScript コードから C 互換な外部ライブラリ関数の呼び出しを可能にします。
ctypes.jsm
JavaScript コードモジュールは chrome ――つまり、アプリケーション自身またはアドオンの内部からだけ利用することができます。ctypes を利用するにはまず、 JavaScript スコープの中にコードモジュールをインポートする必要があります:
Components.utils.import("resource://gre/modules/ctypes.jsm")
一度モジュールをインポートしたら、あとは外部ライブラリを読み込むために利用することができます。
ライブラリを開く
外部ライブラリを利用する前に、開く必要があります。これは ctypes.open()
関数を用いて行います。
var lib = ctypes.open(name);
ライブラリ name
はパス名の文字列、または nsILocalFile
オブジェクトのどちらかで指定できます。
ライブラリが無事に読み込まれると、ctypes.open()
は節「ライブラリオブジェクトの利用」で説明されるライブラリオブジェクトを返します。ライブラリの読み込みに失敗すると、 null
を返します。
ライブラリオブジェクトの利用
一度ライブラリが開かれたら、アクセスしたい
あらゆる関数
を
ライブラリオブジェクトの declare() メソッドを呼び出すことで
宣言する必要があります。
var func = lib.declare(name, abi, returnType, argType1, ...)
- name
- 宣言する関数の名前。これは開いたライブラリの中で妥当なシンボルでなければならない。
- abi
- 利用する呼び出しの取り決め。通常これは
ctypes.default_abi
になるが、関数が Win32 API の場合はctypes.stdcall_abi
を利用する必要がある。 - returnType
- 関数が返す型。これは型定数の一つでなければならない。
- argType1...
- 入力引数型の 0 個以上のリスト。これらは型定数から選ばれなければならない。
一度ライブラリから関数が宣言されたら、ほかの関数と同様に呼び出すことができます。
ライブラリの利用を終えたら、その close()
メソッドを呼んで閉じる必要があります:
lib.close();
型定数
次の定数は ctypes で対応しているデータ型を定義しています。
定数 | 説明 |
ctypes.void_t |
返り型でのみ可能。なにも返さないことを示す。 |
ctypes.bool | 8 ビット真偽値 |
ctypes.int8_t | 8 ビット符号付き整数 |
ctypes.int16_t | 16 ビット符号付き整数 |
ctypes.int32_t | 32 ビット符号付き整数 |
ctypes.int64_t | 64 ビット符号付き整数 |
ctypes.uint8_t | 8 ビット符号なし整数 |
ctypes.uint16_t | 16 ビット符号なし整数 |
ctypes.uint32_t | 32 ビット符号なし整数 |
ctypes.uint64_t | 64 ビット符号なし整数 |
ctypes.float | 浮動小数点数 |
ctypes.double | 倍精度浮動小数点数 |
ctypes.string | C 文字列 (char * ) |
ctypes.ustring | 16 ビット C 文字列 (char16_t * ) |
例: Windows ルーチンの呼び出す
この例は Win32 API を呼び出すために ctypes を利用する方法を説明します。
Components.utils.import("resource://gre/modules/ctypes.jsm"); var lib = ctypes.open("C:\\WINDOWS\\system32\\user32.dll"); /* Declare the signature of the function we are going to call */ var msgBox = lib.declare("MessageBoxW", ctypes.stdcall_abi, ctypes.int32_t, ctypes.int32_t, ctypes.ustring, ctypes.ustring, ctypes.int32_t); var MB_OK = 3; var ret = msgBox(0, "Hello world", "title", MB_OK); lib.close();
3行目で、user32.dll
システムライブラリが読み込まれています。6 行目は Windows 関数 MessageBoxW
を呼び出すメソッドとなる msgBox()
を宣言しています。15 行目は msgBox()
ルーチンを呼び、警告を表示します。
利用を終えたら私たちが最後に行うのは、ライブラリを閉じるために lib.close()
を呼び出すことです。
パスすべてを定義するのではなく、単にファイル名を与えることもできます。
var lib = ctypes.open("user32.dll");
あるいは拡張子抜きで。
var lib = ctypes.open("user32");
フルパスが与えられなかった場合、Windows は DLL 探すために次の検索順を利用します:
- アプリケーションが読み込まれたディレクトリ。
- システムディレクトリ。
- 16 ビットシステムディレクトリ。
- Windows ディレクトリ。
- 現在のディレクトリ。
PATH
環境変数に載っているディレクトリ。
(https://msdn.microsoft.com/ja-jp/library/ms682586%28VS.85%29.aspx より)
例: Mac OS X で Carbon ルーチンの呼び出す
この例は Mac OS X で Carbon 関数を呼び出すために ctypes を利用する方法を説明します。
/* build a Str255 ("Pascal style") string from the passed-in string */ function makeStr(str) { return String.fromCharCode(str.length) + str; } Components.utils.import("resource://gre/modules/ctypes.jsm"); var carbon = ctypes.open("/System/Library/Frameworks/Carbon.framework/Carbon"); stdAlert = carbon.declare("StandardAlert", /* function name */ ctypes.default_abi, /* ABI type */ ctypes.int16_t, /* return type */ ctypes.int16_t, /* alert type */ ctypes.string, /* primary text */ ctypes.string, /* secondary text */ ctypes.uint32_t, /* alert param */ ctypes.int16_t); /* item hit */ var hit = 0; var msgErr = makeStr("Carbon Says..."); var msgExp = makeStr("We just called the StandardAlert Carbon function from JavaScript!"); var err = stdAlert(1, msgErr, msgExp, 0, hit); carbon.close();
The makeStr()
関数は入力として標準の JavaScript 文字列を取り、バイト長の後に文字列そのものの文字が続く Carbon 形式の「Pascal」文字列を返すユーティリティルーチンです。これは文字列が実際に 256 文字以下の場合にだけ正しく動作することを忘れないでください。 長い場合は見事に失敗します。
9 行目で、システムの Carbon フレームワークから Carbon ライブラリが読み込まれています。
11 行目は Carbon の StandardAlert
ルーチンを呼び出す、stdAlert()
関数を宣言しています。既定の ABI を利用し、 16 ビット整数 (Carbon の OSErr
値) を返し、そして整数(警告タイプ)と 2 つの文字列、私たちは利用しないパラメータブロックへのポインタ、ヒットした項目を返すために用いるもう 1 つの整数を受け入れます。詳しくは StandardAlert
に関する Apple の文書を参照してください。
その後、私たちは必要な Str255 文字列を 2 つ生成するために makeStr() を用いて単にパラメータを構成し、
stdAlert()
を呼び出すと、次の警告ウィンドウが作り出されます:
利用を終えたら私たちが最後に行うのは、ライブラリを閉じるために carbon.close()
を呼び出すことです。
例: Linux で LibC ルーチンの呼び出す
この例は Linux で libc 関数を呼び出すために ctypes を利用する方法を説明します。
/* import js-ctypes */ Components.utils.import("resource://gre/modules/ctypes.jsm"); /* open a library */ var libc = ctypes.open("libc.so.6"); /* import a function */ var puts = libc.declare("puts", /* function name */ ctypes.default_abi, /* call ABI */ ctypes.int32_t, /* return type */ ctypes.string /* argument type */ ); var ret = puts("Hello World from js-ctypes!");