Declaring types

  • Revision slug: Mozilla/js-ctypes/Using_js-ctypes/Declaring_types
  • Revision title: Declaring types
  • Revision id: 73094
  • Created:
  • Creator: Sheppy
  • Is current revision? No
  • Comment finish struct example; 26 words added

Revision Content

{{ gecko_minversion_header("2.0") }}{{ draft() }}

The ctypes object offers a number of constructor methods that let you declare types. Every type is represented by a CType object, which, in turn, provides a constructor method you can call to define values of those types. Each type you declare using js-ctypes corresponds to a compatible C declaration.

Types are declared in terms of other, already defined types. At the core of all this is a set of predefined types provided by js-ctypes. These are all primitive types, upon which all other types are eventually based.

Primitive types

Primitive types are those types that represent a single value in memory, as opposed to arrays, structures, or functions. You can define values of these types without declaring new types. For example, to define a new 32-bit integer variable with the value 5:

var i = ctypes.int32_t(5);

You can then pass a pointer to this value to a C function that requires a pointer to a 32-bit integer, like this:

some_c_function(i.address());

Declaring new primitive types

There are times when you want to create new types that are simply new names for existing primitive types. For example, on Windows, you may wish to be able to use the Windows-standard DWORD type name for unsigned 32-bit integers. To declare this type, you can simply do:

const DWORD = ctypes.uint32_t;

After doing this, DWORD is a CType that can then be used to represent 32-bit unsigned integers.

Structures

Structures are declared using the ctypes.StructType() constructor. This method accepts as input the name of the structure and an array of field descriptors, each describing one field in the structure.

Note: At present, there isn't a way to specify that an array's C equivalent was declared as a packed structure; that is, using #pragma pack.

Field descriptors

Each field descriptor is comprised of a field name and its data type, represented as a string and a CType object, respectively. The format, then, looks like this:

[
  { field1: type1 },
  { field2: type2 },
  ...
  { fieldN: typeN }
]

Example

For example, to support the C tm structure using js-ctypes, you would use the following code:

const struct_tm = new ctypes.StructType("tm",
                        [ { "tm_sec": ctypes.int },
                          { "tm_min": ctypes.int },
                          { "tm_hour": ctypes.int },
                          { "tm_mday": ctypes.int },
                          { "tm_mon": ctypes.int },
                          { "tm_year": ctypes.int },
                          { "tm_wday": ctypes.int },
                          { "tm_yday": ctypes.int },
                          { "tm_isdst": ctypes.int } ]);

You can then declare and use a function that uses this structure, like this:

const asctime = lib.declare("asctime", ctypes.default_abi, ctypes.char.ptr, struct_tm.ptr);

var theTime = new struct_tm;
theTime.tm_hour = 3;
theTime.tm_min = 15;
...

var timeStr = asctime(theTime.address());

var jsString = timeStr.readString();

The last line converts the C string returned by the libc asctime() function into a JavaScript string.

Arrays

To declare a new array type, you use the ctypes.ArrayType() method.When declaring a new array type, you provide a CType indicating the type of each element in the array as well as an optional array length. You may declare your array either with a specific number of elements, or with no predetermined size. This is permitted since C allows it, for the widest possible compatibility.

Declaring an array type with unspecified length

To declare a new array type without specifying a length, you simply pass in the CType specifying the element type when calling ctypes.ArrayType(). For example, to create a type for an array of C standard I/O FILE pointers (perhaps for tracking a number of active files on disk):

const FILE = new ctypes.StructType("FILE").ptr;      // Create FILE as a FILE * type
const FileArray = new ctypes.ArrayType(FILE);        // Create a FileArray type

In this example, FILE is an opaque pointer we can use to refer to C FILE records, as defined in stdio.h. FileArray is a new type representing an array of unspecified length, in which each entry is a pointer to a FILE record.

Declaring an array type with a specific length

Declaring an array type that specifies the array length is as simple as adding a length when calling ctypes.ArrayType(), like this:

const FileArray = new ctypes.ArrayType(FILE, 20);

This declares FileArray as an array type that can hold 20 elements.

Pointers

There are two kinds of pointer types:

  • Pointer to a particular type
  • Opaque pointer

Declaring a pointer type is done using the ctypes.PointerType() method.

Declaring a pointer type

Declaring a pointer type as a pointer to a specific type is done by passing as a parameter to the ctypes.PointerType() method a CType object indicating the type to which the pointer should refer:

const IntPtr = new ctypes.PointerType(ctypes.int);

In this example, IntPtr is equivalent to this declaration in C:

typedef int *intPtr;

You can similarly declare a pointer type as a pointer to any user-defined type, including structures:

const UserRecord = new ctypes.StructType("UserRecord",
                        [{"name": ctypes.char.ptr},
                        {"id": ctypes.int32}]);
const UserRecordPtr = new ctypes.PointerType(UserRecord);

In this example, a new UserRecord type is defined, along with a new pointer type that can be used to reference it. The equivalent C code looks like this:

typedef struct UserRecord {
  char *name;
  int id;    // Assuming int is 32-bit here
} UserRecord;

typedef UserRecordPtr *UserRecord;

Declaring an opaque pointer type

Declaring an opaque pointer type is done by passing a string, indicating the name of the pointer type, to the ctypes.PointerType() method:

const HANDLE = new ctypes.PointerType("HANDLE");

This is equivalent to the following type declaration in C:

typedef void *HANDLE;

Revision Source

<p>{{ gecko_minversion_header("2.0") }}{{ draft() }}</p>
<p>The <code><a href="/en/js-ctypes/js-ctypes_reference/ctypes" title="en/js-ctypes/js-ctypes reference/ctypes">ctypes</a></code> object offers a number of constructor methods that let you declare types. Every type is represented by a <a href="/en/js-ctypes/js-ctypes_reference/CType" title="en/js-ctypes/js-ctypes reference/CType"><code>CType</code></a> object, which, in turn, provides a constructor method you can call to define values of those types. Each type you declare using js-ctypes corresponds to a compatible C declaration.</p>
<p>Types are declared in terms of other, already defined types. At the core of all this is a set of <a href="/en/js-ctypes/js-ctypes_reference/ctypes#Predefined_data_types" title="en/js-ctypes/js-ctypes reference/ctypes#Predefined data types">predefined types</a> provided by js-ctypes. These are all primitive types, upon which all other types are eventually based.</p>
<h2>Primitive types</h2>
<p><strong>Primitive types</strong> are those types that represent a single value in memory, as opposed to arrays, structures, or functions. You can define values of these types without declaring new types. For example, to define a new 32-bit integer variable with the value 5:</p>
<pre>var i = ctypes.int32_t(5);
</pre>
<p>You can then pass a pointer to this value to a C function that requires a pointer to a 32-bit integer, like this:</p>
<pre>some_c_function(i.address());
</pre>
<h3>Declaring new primitive types</h3>
<p>There are times when you want to create new types that are simply new names for existing primitive types. For example, on Windows, you may wish to be able to use the Windows-standard <code>DWORD</code> type name for unsigned 32-bit integers. To declare this type, you can simply do:</p>
<pre>const DWORD = ctypes.uint32_t;
</pre>
<p>After doing this, <code>DWORD</code> is a <a href="/en/js-ctypes/js-ctypes_reference/CType" title="en/js-ctypes/js-ctypes reference/CType"><code>CType</code></a> that can then be used to represent 32-bit unsigned integers.</p>
<h2>Structures</h2>
<p>Structures are declared using the <a href="/en/js-ctypes/js-ctypes_reference/ctypes#StructType()" title="en/js-ctypes/js-ctypes reference/ctypes#StructType()"><code>ctypes.StructType()</code></a> constructor. This method accepts as input the name of the structure and an array of <strong>field descriptors</strong>, each describing one field in the structure.</p>
<div class="note"><strong>Note:</strong><strong> </strong>At present, there isn't a way to specify that an array's C equivalent was declared as a packed structure; that is, using <code>#pragma pack</code>.</div>
<h3>Field descriptors</h3>
<p>Each field descriptor is comprised of a field name and its data type, represented as a string and a <a href="/en/js-ctypes/js-ctypes_reference/CType" title="en/js-ctypes/js-ctypes reference/CType"><code>CType</code></a> object, respectively. The format, then, looks like this:</p>
<pre class="brush: js">[
  { field1: type1 },
  { field2: type2 },
  ...
  { fieldN: typeN }
]
</pre>
<h3>Example</h3>
<p>For example, to support the C <code>tm</code> structure using js-ctypes, you would use the following code:</p>
<pre class="brush: js">const struct_tm = new ctypes.StructType("tm",
                        [ { "tm_sec": ctypes.int },
                          { "tm_min": ctypes.int },
                          { "tm_hour": ctypes.int },
                          { "tm_mday": ctypes.int },
                          { "tm_mon": ctypes.int },
                          { "tm_year": ctypes.int },
                          { "tm_wday": ctypes.int },
                          { "tm_yday": ctypes.int },
                          { "tm_isdst": ctypes.int } ]);
</pre>
<p>You can then declare and use a function that uses this structure, like this:</p>
<pre class="brush: js">const asctime = lib.declare("asctime", ctypes.default_abi, ctypes.char.ptr, struct_tm.ptr);

var theTime = new struct_tm;
theTime.tm_hour = 3;
theTime.tm_min = 15;
...

var timeStr = asctime(theTime.address());

var jsString = timeStr.readString();
</pre>
<p>The last line converts the C string returned by the libc <code>asctime()</code> function into a JavaScript string.</p>
<h2>Arrays</h2>
<p>To declare a new array type, you use the <a href="/en/js-ctypes/js-ctypes_reference/ctypes#ArrayType()" title="en/js-ctypes/js-ctypes reference/ctypes#ArrayType()"><code>ctypes.ArrayType()</code></a> method.When declaring a new array type, you provide a <a href="/en/js-ctypes/js-ctypes_reference/CType" title="en/js-ctypes/js-ctypes reference/CType"><code>CType</code></a> indicating the type of each element in the array as well as an optional array length. You may declare your array either with a specific number of elements, or with no predetermined size. This is permitted since C allows it, for the widest possible compatibility.</p>
<h3>Declaring an array type with unspecified length</h3>
<p>To declare a new array type without specifying a length, you simply pass in the <a href="/en/js-ctypes/js-ctypes_reference/CType" title="en/js-ctypes/js-ctypes reference/CType"><code>CType</code></a> specifying the element type when calling <a href="/en/js-ctypes/js-ctypes_reference/ctypes#ArrayType%28%29" title="en/js-ctypes/js-ctypes reference/ctypes#ArrayType()"><code>ctypes.ArrayType()</code></a>. For example, to create a type for an array of C standard I/O <code>FILE</code> pointers (perhaps for tracking a number of active files on disk):</p>
<pre>const FILE = new ctypes.StructType("FILE").ptr;      // Create FILE as a FILE * type
const FileArray = new ctypes.ArrayType(FILE);        // Create a FileArray type
</pre>
<p>In this example, <code>FILE</code> is an opaque pointer we can use to refer to C <code>FILE</code> records, as defined in <a class=" external" href="http://en.wikipedia.org/wiki/Stdio.h" title="http://en.wikipedia.org/wiki/Stdio.h"><code>stdio.h</code></a>. <code>FileArray</code> is a new type representing an array of unspecified length, in which each entry is a pointer to a <code>FILE</code> record.</p>
<h3>Declaring an array type with a specific length</h3>
<p>Declaring an array type that specifies the array length is as simple as adding a length when calling <a href="/en/js-ctypes/js-ctypes_reference/ctypes#ArrayType%28%29" title="en/js-ctypes/js-ctypes reference/ctypes#ArrayType()"><code>ctypes.ArrayType()</code></a>, like this:</p>
<pre>const FileArray = new ctypes.ArrayType(FILE, 20);
</pre>
<p>This declares <code>FileArray</code> as an array type that can hold 20 elements.</p>
<h2>Pointers</h2>
<p>There are two kinds of pointer types:</p>
<ul> <li>Pointer to a particular type</li> <li>Opaque pointer</li>
</ul>
<p>Declaring a pointer type is done using the <a href="/en/js-ctypes/js-ctypes_reference/ctypes#PointerType()" title="en/js-ctypes/js-ctypes reference/ctypes#PointerType()"><code>ctypes.PointerType()</code></a> method.</p>
<h3>Declaring a pointer type</h3>
<p>Declaring a pointer type as a pointer to a specific type is done by passing as a parameter to the <a href="/en/js-ctypes/js-ctypes_reference/ctypes#PointerType%28%29" title="en/js-ctypes/js-ctypes reference/ctypes#PointerType()"><code>ctypes.PointerType()</code></a> method a <a href="/en/js-ctypes/js-ctypes_reference/CType" title="en/js-ctypes/js-ctypes reference/CType"><code>CType</code></a> object indicating the type to which the pointer should refer:</p>
<pre>const IntPtr = new ctypes.PointerType(ctypes.int);
</pre>
<p>In this example, <code>IntPtr</code> is equivalent to this declaration in C:</p>
<pre>typedef int *intPtr;
</pre>
<p>You can similarly declare a pointer type as a pointer to any user-defined type, including structures:</p>
<pre class="brush: js">const UserRecord = new ctypes.StructType("UserRecord",
                        [{"name": ctypes.char.ptr},
                        {"id": ctypes.int32}]);
const UserRecordPtr = new ctypes.PointerType(UserRecord);
</pre>
<p>In this example, a new <code>UserRecord</code> type is defined, along with a new pointer type that can be used to reference it. The equivalent C code looks like this:</p>
<pre class="brush: js">typedef struct UserRecord {
  char *name;
  int id;    // Assuming int is 32-bit here
} UserRecord;

typedef UserRecordPtr *UserRecord;
</pre>
<h3>Declaring an opaque pointer type</h3>
<p>Declaring an opaque pointer type is done by passing a string, indicating the name of the pointer type, to the <a href="/en/js-ctypes/js-ctypes_reference/ctypes#PointerType%28%29" title="en/js-ctypes/js-ctypes reference/ctypes#PointerType()"><code>ctypes.PointerType()</code></a> method:</p>
<pre>const HANDLE = new ctypes.PointerType("HANDLE");
</pre>
<p>This is equivalent to the following type declaration in C:</p>
<pre>typedef void *HANDLE;
</pre>
Revert to this revision