Windows上のFirefox 4でjs-ctypesを使用した経験

私が働いている会社は、インターネットユーザー向けのサポートプログラムを開発しています。 これらのプログラムをfirefoxから呼び出すために、特別な拡張機能があります。 非常に簡単に動作します-システム内のウィンドウを検索し、WM_COPYDATAを介してウィンドウにデータを転送します。 しかし、Windowsプログラムとのこのような相互作用のために、CでXPCOMコンポーネントを作成する必要がありました。 CからJSにコードをコピーしていたときに、共有したいすべての落とし穴に遭遇しました。

コードの簡略版は次のようになります。



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



// - 64 32 . Firefox-64 default_abi, 32 default_abi winapi_abi. default_abi, - .



var CallBackType;

var WinABI;



// FF64 FF32, - size_t, 8 4

if (ctypes.size_t.size == 8) {

CallBackABI = ctypes.default_abi;

WinABI = ctypes.default_abi;

} else {

CallBackABI = ctypes.stdcall_abi;

WinABI = ctypes.winapi_abi;

}



// dll

var user32dll = ctypes.open( 'user32.dll' );

var kernel32dll = ctypes.open( 'kernel32.dll' );



//

const EnumWindowsProc = ctypes.FunctionType(CallBackABI, ctypes. bool , [ctypes.size_t, ctypes.size_t]);



var EnumWindows = user32dll.declare( 'EnumWindows' , WinABI, ctypes. bool , EnumWindowsProc.ptr, ctypes.size_t);



var SendMessage = user32dll.declare( 'SendMessageW' , WinABI, ctypes.size_t, ctypes.size_t, ctypes.unsigned_int, ctypes.size_t, ctypes.size_t);

// , :

//const HWND = ctypes.size_t;

//const WPARAM = ctypes.size_t;

//const LPARAM = ctypes.size_t;

//const LRESULT = ctypes.size_t;

//const UINT = ctypes.unsigned_int;

//SendMessage = user32dll.declare('SendMessageW', WinABI, LRESULT, HWND, UINT, WPARAM, LPARAM);



var GetClassName = user32dll.declare( 'GetClassNameW' , WinABI, ctypes. int , ctypes.size_t, ctypes.jschar.ptr, ctypes. int );



var WideCharToMultiByte = kernel32dll.declare( 'WideCharToMultiByte' , WinABI, ctypes. int , ctypes.unsigned_int, ctypes.uint32_t, ctypes.jschar.ptr, ctypes. int , ctypes. char .ptr, ctypes. int , ctypes. char .ptr, ctypes. bool .ptr);



const WM_COPYDATA = 74;



// COPYDATA

const COPYDATASTRUCT = new ctypes.StructType( 'COPYDATASTRUCT' ,

[ { 'dwData' : ctypes.uintptr_t},

{ 'cbData' : ctypes.uint32_t},

{ 'lpData' : ctypes.voidptr_t}

]);



// XPCOM UTF-16, UTF-8. - , UTF-16 ,

function Wide2Ansi(str) {

if (str) {

var i = WideCharToMultiByte(CP_ACP, 0, str, -1, null , 0, null , null );

// . new - , -

var buf = new new ctypes.ArrayType(ctypes. char , i);

i = WideCharToMultiByte(CP_ACP, 0, str, -1, buf, i, null , null );

//- , , buf.readString(),

if (i)

return buf;

}

return null ;

}



// , Windows

function SearchPD(hwnd, lParam) {

var result = true ;



var buf = new new ctypes.ArrayType(ctypes.jschar, 255);

GetClassName(hwnd, buf, 255);

if (buf.readString() == 'TMainForm' ) {

//

ctypes.size_t.ptr(lParam).contents = hwnd;

result = false ;

}

return result;

}



function GetHwnd() {

// -

var SearchPD_ptr = EnumWindowsProc.ptr(SearchPD);

// , -

var wnd = ctypes.size_t(0);



// , ctypes.cast

EnumWindows(SearchPD_ptr, ctypes.cast(wnd.address(), ctypes.size_t));

// ,

return wnd.address().contents;

}



var hWnd = GetHwnd();

//- , ctypes.size_t 64 , , , if (hWnd) , hWnd.

if (hWnd != 0) {

var command = 'hWnd=' + hWnd;



var CD = new COPYDATASTRUCT();



// Ansi UTF-8 UTF-16 ctypes.jschar.array()

var cmd = Wide2Ansi(ctypes.jschar.array()(command))

if (cmd) {

CD.lpData = cmd.address();

CD.cbData = cmd.length - 1;

CD.dwData = 0;

SendMessage(hWnd, WM_COPYDATA, 0, ctypes.cast(CD.address(), ctypes.size_t));

}

}




* This source code was highlighted with Source Code Highlighter .






サンプルを読みやすくするために、コードを大幅に簡素化したため、コードはあまり意味がありませんでした。 Mozillaサイトからアドオンをダウンロードすることで、作業中のバージョンを確認できます(新しいバージョン1.5は、ベータ版としてのみ利用可能です)。



All Articles