拡張機能の作成者、ブラウザハッカー、js-ctypesに会う

js-ctypesとは何ですか(尋ねることができます)? 拡張機能をJavaScriptで記述し、ローカルコード(ネイティブコード)を参照する必要があるとします たとえば、weave-cryptoはNSSライブラリにアクセスする必要があります。 そして、拡張機能は、たとえばNSPR、libc、またはWin32関数を直接呼び出したい場合があります。 現在、2つの方法があります。スクリプト可能なXPCOMインターフェイス(libxulで提供)を使用するか、独自のXPCOMインターフェイスを記述して実装する、つまり拡張機能でバイナリコードを提供するかのいずれかです。 最初のオプションが失敗した場合、2番目のオプションのみが残りますが、拡張機能の配布は著しく難しくなります:クロスプラットフォームxpi内にパックするには、サポートされている各プラットフォームのバイナリコードを個別にコンパイルする必要があります。



したがって、この難しさの答えはjs-ctypesライブラリになります。JavaScriptがローカルコード(Cで記述された)を呼び出し、XPCOMを使用せずにデータ型を操作できるようにします。1行のコードをコンパイルする必要はありません。 これは、XPCOMインターフェースを定義する必要がなく、libcのような共有ライブラリを直接使用できることを意味します。 副次的なプラスの効果があります。ほとんどの場合、XPConnectに固有のデータ型変換が排除されるため、コードの実行が高速になります。 (次のブログエントリの1つで速度の比較を行います。)js-ctypesライブラリはGecko 1.9.3に同梱され、このプラットフォーム(バージョン番号が変更されない場合)がFirefox 3.7の基盤になります。



あなたは尋ねるかもしれません:「しかし、どのように...?」 そして、いくつかの例があります(x86 32ビットLinuxでテストされ、 非クロスプラットフォームパーツが含まれています)。



1)ライブラリを開きます。
// ctypes.

Components.utils.import( "resource://gre/modules/ctypes.jsm" );



// libc.

let library = ctypes.open( "libc.so.6" );



// fopen, -:

// FILE* fopen(const char* name, const char* mode);

let fopen = library.declare( "fopen" , //

ctypes.default_abi, // cdecl

ctypes.PointerType( "FILE*" ), // (FILE*)

ctypes. char .ptr, // (const char*)

ctypes. char .ptr); // (const char*)



// , FILE*.

let file = fopen( "hello world.txt" , "w" );



// 'file'?

file.toString();

// "ctypes.PointerType("FILE*")(ctypes.UInt64("0x9781b38"))" ( )



// ... ...




* This source code was highlighted with Source Code Highlighter .






2)構造タイプ(構造)と配列の定義と使用。
// struct 'hostent', ,

// .

// :

// struct hostent {

// char* h_name; //

// char** h_aliases; // ,

// int h_addrtype; // IPv4 IPv6

// int h_length; // ( ) IP-

// char** h_addr_list; // IP- ( )

// };

let hostent = ctypes.StructType( "hostent" ,

[{ h_name : ctypes. char .ptr },

{ h_aliases : ctypes. char .ptr.ptr },

{ h_addrtype : ctypes. int },

{ h_length : ctypes. int },

{ h_addr_list : ctypes.uint8_t.array(4).ptr.ptr }]);



// 'gethostbyname', -:

// struct hostent* gethostbyname(const char* name);

let gethostbyname = library.declare( "gethostbyname" ,

ctypes.default_abi,

hostent.ptr, // 'hostent'

ctypes. char .ptr);



// .

let google = gethostbyname( "mail.google.com" );



// struct 'hostent',

// 'h_name',

// . :

// printf("%s", google->h_name);

google.contents.h_name.readString();

// "googlemail.l.google.com"



// 'h_addr_list',

// ,

// IPv4- .

// -:

// printf("%u.%u.%u.%u", (int) h_addr_list[0][0], (int) h_addr_list[0][1],

// (int) h_addr_list[0][2], (int) h_addr_list[0][3]);

google.contents.h_addr_list.contents.contents.toString();

// "ctypes.uint8_t.array(4)([74, 125, 19, 17])" , 74.125.19.17




* This source code was highlighted with Source Code Highlighter .






3)JavaScript関数を指すCのような関数ポインターを作成します。



(ライブラリのこの部分はまだ準備ができていませんが、パッチの作業が進行中であることに注意してください。)
// ,

// , :

// -1, i < j;

// 0, i == j;

// 1, i > j.

// - :

// typedef int (comparator_t*)(const int8_t* i, const int8_t* j);

let comparator_t = ctypes.FunctionType(ctypes.default_abi, ctypes. int ,

ctypes.int8_t.ptr, ctypes.int8_t.ptr);



// - 'comparator_t'?

comparator_t.name;

// "int (*)(int8_t*,int8_t*)"



// 'qsort', ,

// , .

// void qsort(void* array, size_t length, size_t elemsize, comparator_t comp);

let qsort = library.declare( "qsort" , ctypes.default_abi, ctypes.void_t,

ctypes.voidptr_t, ctypes.size_t, ctypes.size_t, comparator_t);



// , 'comparator_t'.

function reverse(i, j) { return j.contents - i.contents; }



// , .

let reverse_ptr = comparator_t(reverse);



// 'reverse_ptr'?

reverse_ptr.toString();

// "ctypes.FunctionType(ctypes.default_abi, ctypes.int, ctypes.int8_t.ptr,

// ctypes.int8_t.ptr)(ctypes.UInt64("0x81a430cb"))"



// 'qsort'.

let array_t = ctypes.int8_t.array();

let ints = array_t([3, 1, 5, 6, 4, 2]);

qsort(ints.address(), ints.length, array_t.elementType.size, reverse_ptr);



// !

ints.toString();

// "ctypes.int8_t.array(6)([6, 5, 4, 3, 2, 1])"




* This source code was highlighted with Source Code Highlighter .






そのため、拡張機能の作成者、 または ブラウザ用のコード 作成する場合は、 js-ctypes を念頭に置い てください



All Articles