ctypes.jsm

  • Revision slug: JavaScript_code_modules/ctypes.jsm
  • Revision title: ctypes.jsm
  • Revision id: 71802
  • Created:
  • Creator: Ted_Mielczarek
  • Is current revision? No
  • Comment 1 words added, 12 words removed

Revision Content

{{ gecko_minversion_header("2") }}

{{ note("The ctypes.jsm code module is undergoing some API revisions to enhance functionality; this documentation will be revised when that's done.") }}

The ctypes.jsm JavaScript code module makes it possible to call C-compatible foreign library functions from JavaScript code without having to write your own binary XPCOM component.

{{ note("The ctypes.jsm JavaScript code module can only be used from chrome -- that is, from within the application itself or an add-on.") }}

To use ctypes, you first need to import the code module into your JavaScript scope:

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

Once you've imported the module, you can then use it to load a foreign library.

Opening a library

Before you can use a foreign library, you need to open it. This is done using the ctypes.open() function.

var lib = ctypes.open(name);

The library name must be specified by a pathname string.

If the library is loaded successfully, ctypes.open() returns a library object, as described in the section Using the library object. If the library fails to load, null is returned.

Using the library object

Once the library is opened, you need to declare any functions you wish to access by calling the library object's declare() method.

var func = lib.declare(name, abi, returnType, argType1, ...)
name
The name of the function to declare; this must be a valid symbol in the opened library.
abi
The calling convention to use. Typically this will be ctypes.default_abi, but if the function is a Win32 API, you need to use ctypes.stdcall_abi.
returnType
The function's return type. This must be one of the type constants.
argType1...
A list of zero or more input argument types; these must be selected from the type constants.

Once a function from the library has been declared, you can call it like any other function.

When you're finished using the library, you need to close it by calling its close() method:

lib.close();

Type constants

The following constants define the data types supported by ctypes.

Constant Description
ctypes.void_t Only allowed for return types; indicates that nothing is returned.
ctypes.bool 8-bit boolean.
ctypes.int8_t 8-bit signed integer.
ctypes.int16_t 16-bit signed integer.
ctypes.int32_t 32-bit signed integer.
ctypes.int64_t 64-bit signed integer.
ctypes.uint8_t 8-bit unsigned integer.
ctypes.uint16_t 16-bit unsigned integer.
ctypes.uint32_t 32-bit unsigned integer.
ctypes.uint64_t 64-bit unsigned integer.
ctypes.float Floating point number.
ctypes.double Double-precision floating-point number.

Example: 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.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();

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.

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

Or even without the extension.

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

If the full path is not given, Windows uses the following search order to locate the DLL:

  1. The directory from which the application loaded.
  2. The system directory.
  3. The 16-bit system directory.
  4. The Windows directory.
  5. The current directory.
  6. The directories that are listed in the PATH environment variable.

(taken from http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx)

Example: Calling Carbon routines on Mac OS X

This example demonstrates how to use ctypes to call a Carbon function on Mac 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.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() 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.

Example: Calling LibC routines on Linux

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

/* 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!");

See also

{{ languages({ "ja": "ja/JavaScript_code_modules/ctypes.jsm" }) }}

Revision Source

<p>{{ gecko_minversion_header("2") }}</p>
<p>{{ note("The <code>ctypes.jsm</code> code module is undergoing some API revisions to enhance functionality; this documentation will be revised when that's done.") }}</p>
<p>The <code>ctypes.jsm</code> JavaScript code module makes it possible to call C-compatible foreign library functions from JavaScript code without having to write your own binary XPCOM component.</p>
<p>{{ note("The <code>ctypes.jsm</code> JavaScript code module can only be used from chrome -- that is, from within the application itself or an add-on.") }}</p>
<p>To use ctypes, you first need to import the code module into your JavaScript scope:</p>
<pre class="eval"><span class="nowiki">Components.utils.import("resource://gre/modules/ctypes.jsm")</span></pre>
<p>Once you've imported the module, you can then use it to load a foreign library.</p>
<h2>Opening a library</h2>
<p>Before you can use a foreign library, you need to open it. This is done using the <code>ctypes.open()</code> function.</p>
<pre>var lib = ctypes.open(name);
</pre>
<p>The library <code>name</code> must be specified by a pathname string.</p>
<p>If the library is loaded successfully, <code>ctypes.open()</code> returns a library object, as described in the section <a href="/en/JavaScript/Code_modules/ctypes.jsm#Using_the_library_object" title="en/JavaScript code modules/ctypes.jsm#Using the library object">Using the library object</a>. If the library fails to load, <code>null</code> is returned.</p>
<h2>Using the library object</h2>
<p>Once the library is opened, you need to declare any functions you wish to access by calling the library object's <code>declare()</code> method.</p>
<pre>var func = lib.declare(name, abi, returnType, argType1, ...)
</pre>
<dl> <dt>name</dt> <dd>The name of the function to declare; this must be a valid symbol in the opened library.</dd> <dt>abi</dt> <dd>The calling convention to use. Typically this will be <code>ctypes.default_abi</code>, but if the function is a Win32 API, you need to use <code>ctypes.stdcall_abi</code>.</dd> <dt>returnType</dt> <dd>The function's return type. This must be one of the <a href="/en/JavaScript/Code_modules/ctypes.jsm#Type_constants" title="en/JavaScript code modules/ctypes.jsm#Type constants">type constants</a>.</dd> <dt>argType1...</dt> <dd>A list of zero or more input argument types; these must be selected from the <a href="/en/JavaScript/Code_modules/ctypes.jsm#Type_constants" title="en/JavaScript code modules/ctypes.jsm#Type constants">type constants</a>.</dd>
</dl>
<p>Once a function from the library has been declared, you can call it like any other function.</p>
<p>When you're finished using the library, you need to close it by calling its <code>close()</code> method:</p>
<pre>lib.close();
</pre>
<h2>Type constants</h2>
<p>The following constants define the data types supported by ctypes.</p>
<table class="standard-table"> <tbody> <tr> <td class="header">Constant</td> <td class="header">Description</td> </tr> <tr> <td><code>ctypes.void_t</code></td> <td>Only allowed for return types; indicates that nothing is returned.</td> </tr> <tr> <td><code>ctypes.bool</code></td> <td>8-bit boolean.</td> </tr> <tr> <td><code>ctypes.int8_t</code></td> <td>8-bit signed integer.</td> </tr> <tr> <td><code>ctypes.int16_t</code></td> <td>16-bit signed integer.</td> </tr> <tr> <td><code>ctypes.int32_t</code></td> <td>32-bit signed integer.</td> </tr> <tr> <td><code>ctypes.int64_t</code></td> <td>64-bit signed integer.</td> </tr> <tr> <td><code>ctypes.uint8_t</code></td> <td>8-bit unsigned integer.</td> </tr> <tr> <td><code>ctypes.uint16_t</code></td> <td>16-bit unsigned integer.</td> </tr> <tr> <td><code>ctypes.uint32_t</code></td> <td>32-bit unsigned integer.</td> </tr> <tr> <td><code>ctypes.uint64_t</code></td> <td>64-bit unsigned integer.</td> </tr> <tr> <td><code>ctypes.float</code></td> <td>Floating point number.</td> </tr> <tr> <td><code>ctypes.double</code></td> <td>Double-precision floating-point number.</td> </tr> </tbody>
</table>
<h2>Example: Calling Windows routines</h2>
<p>This example demonstrates how to use ctypes to call a Win32 API.</p>
<pre class="brush: js">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();</pre>
<p>In line 3, the <code>user32.dll</code> system library is loaded. Line 6 declares <code>msgBox()</code> to be a method that calls the Windows function <a class=" external" href="http://msdn.microsoft.com/en-us/library/ms645505%28VS.85%29.aspx" title="http://msdn.microsoft.com/en-us/library/ms645505(VS.85).aspx"><code>MessageBoxW</code></a>. Line 15 calls the <code>msgBox()</code> routine, which displays the alert.</p>
<p>The last thing we do is call <code>lib.close()</code> to close the library when we're done using it.</p>
<p>Instead of defining the whole path, you may also just give the file name.</p>
<pre>var lib = ctypes.open("user32.dll");
</pre>
<p>Or even without the extension.</p>
<pre>var lib = ctypes.open("user32");
</pre>
<p>If the full path is not given, Windows uses the following search order to locate the DLL:</p>
<ol> <li>The directory from which the application loaded.</li> <li>The system directory.</li> <li>The 16-bit system directory.</li> <li>The Windows directory.</li> <li>The current directory.</li> <li>The directories that are listed in the PATH environment variable.</li>
</ol>
<p>(taken from <a class=" external" href="http://msdn.microsoft.com/en-us/library/ms682586%28VS.85%29.aspx" title="http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx</a>)</p>
<h2>Example: Calling Carbon routines on Mac OS X</h2>
<p>This example demonstrates how to use ctypes to call a Carbon function on Mac OS X.</p>
<pre class="brush: js">/* 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();
</pre>
<p>The <code>makeStr()</code> 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.</p>
<p>In line 9, the Carbon library is loaded from the system's Carbon framework.</p>
<p>Line 11 declares the <code>stdAlert()</code> function, which will call the Carbon <code>StandardAlert</code> routine. It uses the default ABI, returns a 16-bit integer (which is a Carbon <code>OSErr</code> 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 <a class=" external" href="http://developer.apple.com/legacy/mac/library/documentation/Carbon/Reference/Dialog_Manager/Reference/reference.html#//apple_ref/c/func/StandardAlert" title="http://developer.apple.com/legacy/mac/library/documentation/Carbon/Reference/Dialog_Manager/Reference/reference.html#//apple_ref/c/func/StandardAlert"><code>StandardAlert</code></a> for details.</p>
<p>After that, we simply set up our parameters by using <code>makeStr()</code> to generate the two <code>Str255</code> strings we need, then call <code>stdAlert()</code>, which produces the following alert window:</p>
<p><img alt="ctype-mac-dialog.png" class="internal default" src="/@api/deki/files/3842/=ctype-mac-dialog.png"></p>
<p>The last thing we do is call <code>carbon.close()</code> to close the library when we're done using it.</p>
<h2>Example: Calling LibC routines on Linux</h2>
<p>This example demonstrates how to use ctypes to call a libc function on Linux.</p>
<pre class="brush: js">/* 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!");
</pre>
<h2>See also</h2>
<ul> <li><a class="internal" href="/en/JavaScript/Code_modules/Using" title="en/JavaScript code modules/Using
    JavaScript code modules">Using JavaScript code modules</a></li> <li><a class="internal" href="/en/JavaScript/Code_modules" title="en/JavaScript code modules">JavaScript code modules</a></li> <li><a class="internal" href="/en/Components.utils.import" title="en/Components.utils.import"><code>Components.utils.import</code></a></li>
</ul>
<p>{{ languages({ "ja": "ja/JavaScript_code_modules/ctypes.jsm" }) }}</p>
Revert to this revision