mozilla
Your Search Results

    Using js-ctypes

    This article is in need of a technical review.

    この記事はまだ日本語に翻訳されていません。MDN の翻訳はボランティアによって行われています。是非 MDN に登録し、私たちの力になって下さい。

    Draft
    This page is not complete.

    Before you can use js-ctypes, you need to import the ctypes.jsm code module. This is as simple as including the following line of code in the desired JavaScript scope:

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

    Loading a native library

    Once you've imported the code module, you can call the ctypes.open() method to load each native library you wish to use. On Windows, for example, you might load the system user32 library like this:

    var lib = ctypes.open("user32.dll");

    On Mac OS X, you can load the Core Foundation library from the Core Foundation framework like this:

    var coreFoundation = ctypes.open("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation");

    The returned object is a Library object that you use to declare functions and data types for use with the loaded library.

    Note: js-ctypes only works with C libraries; you can't use C++ methods directly. Instead, you'll need to create a shim library that uses C functions that then call into the C++ library for you. Examples can be found here: Bugzilla :: Bug 505907 - Support C++ calling from JSctypes

    Library search paths

    If you specify a full path, that path is used to load the library. Otherwise, the system looks for the library in its standard locations.

    Windows

    On Windows, the following locations are searched for the library, in this order:

    1. The application's directory.
    2. The system directory.
    3. The 16-bit system directory.
    4. The Windows directory.
    5. The current working directory
    6. The directories listed in the PATH environment variable.
    Note: This information comes from this article on MSDN.

    After you're done

    When you're finished using a library, you should close it by calling the Library object's close() method:

    lib.close();

    If you fail to close the library, it will be automatically closed when it is garbage collected.

    Using the library

    You may need to declare new types. These can be simple types or more complex types such as structures. See Declaring types for details. You will almost certainly need to declare one or more functions, so that you can call them.

    Once you've declared the types and functions, you can write your code to make use of them. Instantiating C data objects and referencing them is covered in the article Working with data.

    Memory management

    moved to Memory Management page.

    Examples

    These examples offer a quick look at how js-ctypes is used. See js-ctypes examples for more intricate examples.

    Calling Windows routines

    This example demonstrates how to use ctypes to call a Win32 API.

    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.winapi_abi,
                             ctypes.int32_t,
                             ctypes.int32_t,
                             ctypes.jschar.ptr,
                             ctypes.jschar.ptr,
                             ctypes.int32_t);
    var MB_OK = 0;
    
    var ret = msgBox(0, "Hello world", "title", MB_OK);
    
    lib.close();

    In line 3, the user32.dll system library is loaded. Line 6 declares msgBox() to be a method that calls the Windows function MessageBoxW. Line 15 calls the msgBox() routine, which displays the alert.

    The last thing we do is call lib.close() to close the library when we're done using it.

    Instead of defining the whole path, you may also just give the file name.

    ABOUT DECLARING THE FUNCTION

    How we knew how to declare the function was by going to MSDN site and looking at the MessageBox (MessageBoxW is just a unicode version of same function) function. Also learn about the lib.declare function used here: lib.declare. Learn about the data types used here: Data Types. We see that it needs to be defined like this:

    int WINAPI MessageBox(
      _In_opt_  HWND hWnd,
      _In_opt_  LPCTSTR lpText,
      _In_opt_  LPCTSTR lpCaption,
      _In_      UINT uType
    );

    So we read this article here on defining types and replicate it: Declaring Types

    var lib = ctypes.open("user32.dll");
    

    Or even without the extension.

    var lib = ctypes.open("user32");
    

    Calling Carbon routines on Mac OS X

    This example demonstrates how to use ctypes to call a Carbon function on Mac OS X.

    Note: This example will not work on 64bit OS X, see below for Core Foundation for 64bit OS X
    /* 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.char.ptr,       /* primary text */
                              ctypes.char.ptr,       /* 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() function is a utility routine that takes as input a standard JavaScript string and returns a Carbon-style "Pascal" string, which is a length byte followed by the characters of the string itself. Note that this only works correctly if the string is in fact under 256 characters; if it's longer, this will fail spectacularly.

    In line 9, the Carbon library is loaded from the system's Carbon framework.

    Line 11 declares the stdAlert() function, which will call the Carbon StandardAlert routine. It uses the default ABI, returns a 16-bit integer (which is a Carbon OSErr value), and accepts an integer (the alert type), two strings, a pointer to a parameter block, which we aren't using, and another integer, which is used to return the hit item. See Apple's documentation for StandardAlert for details.

    After that, we simply set up our parameters by using makeStr() to generate the two Str255 strings we need, then call stdAlert(), which produces the following alert window:

    ctype-mac-dialog.png

    The last thing we do is call carbon.close() to close the library when we're done using it.

    Standard Alert in 64bit OS X

    Carbon is not available in 64bit versions of OS X, therefore Core Foundation must be used. The below will do the same as StandardAlert from above, it will use the Core Foundation function of CFUserNotificationDisplayNotice.

    Cu.import('resource://gre/modules/ctypes.jsm');
    var libcf = ctypes.open('/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation');
    
    // DEFINE TYPES
    var CFIndex = ctypes.long;
    var CFOptionFlags = ctypes.unsigned_long;
    var CFTimeInterval = ctypes.double;
    var CFTypeRef = ctypes.voidptr_t;
    var SInt32 = ctypes.long;
    var VOID = ctypes.void_t;
    
    var __CFString = new ctypes.StructType("__CFString");
    var CFStringRef = __CFString.ptr;
    
    var __CFURL = new ctypes.StructType("__CFURL");
    var CFURLRef = __CFURL.ptr;
    
    var __CFAllocator = new ctypes.StructType("__CFAllocator");
    var CFAllocatorRef = __CFAllocator.ptr;
    
    var UniChar = ctypes.jschar;   // uint16 with automatic conversion
    
    // DEFINE CONSTANTS
    var kCFUserNotificationStopAlertLevel = 0;
    var kCFUserNotificationNoteAlertLevel = 1;
    var kCFUserNotificationCautionAlertLevel = 2;
    var kCFUserNotificationPlainAlertLevel = 3;
    
    // DECLARE FUNCTIONS
    /* https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFUserNotificationRef/index.html#//apple_ref/c/func/CFUserNotificationDisplayNotice
     * SInt32 CFUserNotificationDisplayNotice (
     *   CFTimeInterval timeout,
     *   CFOptionFlags flags,
     *   CFURLRef iconURL,
     *   CFURLRef soundURL,
     *   CFURLRef localizationURL,
     *   CFStringRef alertHeader,
     *   CFStringRef alertMessage,
     *   CFStringRef defaultButtonTitle
     * ); 
     */
    var CFUserNotificationDisplayNotice = libcf.declare("CFUserNotificationDisplayNotice", ctypes.default_abi,
    	SInt32,				// return
    	CFTimeInterval,		// timeout
    	CFOptionFlags,		// flags
    	CFURLRef,			// iconURL
    	CFURLRef,			// soundURL
    	CFURLRef,			// localizationURL
    	CFStringRef,		// alertHeader
    	CFStringRef,		// alertMessage
    	CFStringRef			// defaultButtonTitle
    );
    
    /* https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/func/CFRelease
     * void CFRelease (
     *   CFTypeRef cf
     * ); 
     */
    var CFRelease = libcf.declare('CFRelease', ctypes.default_abi,
    	VOID,		// return
    	CFTypeRef	// cf
    );
    
    /* https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFStringRef/#//apple_ref/c/func/CFStringCreateWithCharacters
     * CFStringRef CFStringCreateWithCharacters (
     *   CFAllocatorRef alloc,
     *   const UniChar *chars,
     *   CFIndex numChars
     * ); 
     */
    var CFStringCreateWithCharacters = libcf.declare('CFStringCreateWithCharacters', ctypes.default_abi,
    	CFStringRef,		// return
    	CFAllocatorRef,		// alloc
    	UniChar.ptr,		// *chars
    	CFIndex				// numChars
    );
    
    // HELPER FUNCTIONS
    function makeCFStr(jsStr) {
    	// js str is just a string
    	// returns a CFStr that must be released with CFRelease when done
    	return CFStringCreateWithCharacters(null, jsStr, jsStr.length);
    }
    
    // MAIN
    var myCFStrs = {
    	head: makeCFStr('Core Foundation Says...'),
    	body: makeCFStr('We just called the equivalent of the "StandardAlert Carbon function" for 64bit OSX from JavaScript!')
    };
    
    var rez = CFUserNotificationDisplayNotice(0, kCFUserNotificationCautionAlertLevel, null, null, null, myCFStrs.head, myCFStrs.body, null);
    console.info('rez:', rez, rez.toString(), uneval(rez)); // CFUserNotificationDisplayNotice does not block till user clicks dialog, it will return immediately
    
    if (rez.toString() == '0') {
        console.log('Notification was succesfully shown!!');
    } else {
        console.error('Failed to show notification... :(');
    }
    
    for (var cfstr in myCFStrs) {
    	if (myCFStrs.hasOwnProperty(cfstr)) {
    		var rez_CFRelease = CFRelease(myCFStrs[cfstr]); // returns void
    	}
    }
    
    libcf.close();

    Calling LibC routines on Linux/POSIX

    This example demonstrates how to use ctypes to call a libc function on Linux.

    /* import js-ctypes */
    var {Cu} = require("chrome");
    var {ctypes} = Cu.import("resource://gre/modules/ctypes.jsm", null);
    
    /* Open the library */
    try {
      /* Linux */
      var libc = ctypes.open("libc.so.6");
    } catch (e) {
      /* Most other Unixes */
      libc = ctypes.open("libc.so");
    }
    
    /* Import a function */
    var puts = libc.declare("puts",             /* function name */
                            ctypes.default_abi, /* call ABI */
                            ctypes.int,         /* return type */
                            ctypes.char.ptr);   /* argument type */
    
    var ret = puts("Hello World from js-ctypes!");
    
    libc.close();
    

    ドキュメントのタグと貢献者

    最終更新者: arai,