638
edits
(add jorendorff stuff, partly compatible) |
|||
| Line 1: | Line 1: | ||
==== 1. opening a library and declaring a function ==== | ==== 1. opening a library and declaring a function ==== | ||
<pre>Cu.import("ctypes"); // imports the global ctypes object | <pre>Cu.import("ctypes"); // imports the global ctypes object | ||
| Line 91: | Line 89: | ||
let v = new v_t(new Pointer(s), new Pointer(s));</pre> | let v = new v_t(new Pointer(s), new Pointer(s));</pre> | ||
In this case, the fields array will each have their respective Pointer as the parent object, and both will point to the s binary blob.<br> | In this case, the fields array will each have their respective Pointer as the parent object, and both will point to the s binary blob.<br> | ||
---- | |||
'''js-ctypes''' is a library for calling C/C++ functions from JavaScript without having to write or generate any C/C++ "glue code". | |||
js-ctypes is already in mozilla-central, but the API is subject to change. This page contains design proposals for the eventual js-ctypes API. | |||
= Types = | |||
A ''type'' maps JS values to C/C++ values and vice versa. They're used when declaring functions. They can also be used to create and populate C/C++ data structures entirely from JS. | |||
== The types provided by ctypes == | |||
'''ctypes.int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float32_t, float64_t''' - Primitive types that behave the same way on all platforms (with the usual caveat that every platform has slightly different floating-point behavior, in corner cases, and there's nothing we can realistically do about it). | |||
'''ctypes.bool, short, unsigned_short, int, unsigned, unsigned_int, long, unsigned_long, float, double''' - Types that behave like the corresponding C types. Some or all of these might be aliases for the primitive types listed above. As in C, ''unsigned'' is always an alias for ''unsigned_int''. | |||
''(Note: I think <code>int</code> might be reserved in JS, sigh.)'' | |||
''(TBD: Do we want char types? how should they behave?)'' | |||
'''ctypes.string, ustring''' - String types. The C/C++ type for <code>ctypes.string</code> is <code>const char *</code>. C/C++ values of this type must be either <code>null</code> or pointers to null-terminated strings. <code>ctypes.ustring</code> is the same, but for <code>const jschar *</code>; that is, the code units of the string are <code>uint16_t</code>. | |||
'''ctypes.void_t''' - The special C type <code>void</code>. This can be used as a return value type. (<code>void</code> is a keyword in JavaScript.) | |||
'''ctypes.PointerType''' - Constructor for pointer types. ''new ctypes.PointerType(T)'', where ''T'' is a type, creates the type "pointer to ''T''". Also ''new ctypes.PointerType(name)'', where ''name'' is a string, creates an opaque pointer type. | |||
'''ctypes.ArrayType''' - Constructor for array types. ''new ctypes.ArrayType(T, n)'', where ''T'' is a type and ''n'' is a nonnegative integer, creates the type ''T''[''n'']. | |||
'''ctypes.StructType''' - Constructor for struct types. ''new ctypes.StructType(name, fields)'' creates a new struct named "struct ''name''" with the given fields (fields is an array of field descriptors), details TBD. | |||
Examples: | |||
const DWORD = ctypes.uint32_t; | |||
const HANDLE = new ctypes.PointerType("HANDLE"); | |||
const FILE = new ctypes.PointerType("FILE *"); | |||
const IOBuf = new ctypes.ArrayType(ctypes.uint8_t, 4096); | |||
const struct_tm = new ctypes.Struct('tm', [[ctypes.int, 'tm_sec'], ...]); | |||
== Calling types == | |||
js-ctypes types are JavaScript constructors. That is, they are functions, and they can be called in various different ways. (<code>ctypes.Buffer</code> and <code>ctypes.Reference</code> are to be described below.) | |||
'''new ''t''''' or '''new ''t''()''' - Without arguments, these allocate a new <code>ctypes.Buffer</code> of <code>''t''.size</code> bytes, populate it with zeroes, and return a new <code>ctypes.Reference</code> to the complete object in that <code>Buffer</code>. | |||
'''''t''()''' - The same, but if the resulting value can be precisely represented as a JavaScript primitive value (boolean, number, string, null, undefined), return that instead. (This is the case for all number types, string types, pointer types, <code>ctypes.bool</code>, and <code>ctypes.void_t</code>.) | |||
'''new ''t''(''ref'')''' - With a single argument that is a reference to an object of size <code>''t''.size</code>, this creates a new <code>Buffer</code> and <code>Reference</code> as above, but populates the buffer with a copy of the object referred to by ''ref'' rather than zeroing it out. | |||
'''new ''t(''val'')''' - With an argument that is any other JavaScript value, this converts the value to type ''t'', throwing a <code>TypeError</code> if the conversion is impossible, then creates a new <code>Buffer</code> and <code>Reference</code> as above, populating the new buffer with the converted value. Details of conversion depend on the type. | |||
'''''t''(''val'')''' - Convert ''val'' to type ''t'' as above. If the result can be precisely represented as a JavaScript primitive value (boolean, number, string, <code>null</code>, or <code>undefined</code>) or a ctypes pointer, return that. Otherwise return a new Reference, exactly as for <code>new ''t''(''val'')</code>. | |||
The special type <code>ctypes.void_t</code> throws a <code>TypeError</code> if called with <code>new</code>, but <code>ctypes.void_t()</code> and <code>ctypes.void_t(''x'')</code> are allowed. Both return <code>undefined</code>. | |||
== Properties of types == | |||
All types have these properties: | |||
'''''t''.size''' - The C/C++ <code>sizeof</code> the type, in bytes. | |||
<code>ctypes.void_t.size</code> is 0. | |||
'''''t''.name''' - A string, the type's name. It's intended that in ordinary use, this will be a C/C++ type expression, but it's not really meant to be machine-readable in all cases. | |||
For primitive types this is just the name of the corresponding C/C++ type, e.g. <code>ctypes.int32_t.name == "int32_t"</code> and <code>ctypes.void_t == "void"</code>. But some of the builtin types are aliases for other types, so it might be that <code>ctypes.unsigned_long.name == "uint32_t"</code> (or something else). ''(Is that too astonishing?)'' | |||
For struct types and opaque pointer types, this is simply the string that was passed to the constructor; e.g. <code>FILE.name == "FILE *"</code> and <code>struct_tm.name == "tm"</code>. For other pointer types and array types this should try to generate valid C/C++ type expressions, which isn't exactly trivial. | |||
''(Should you be able to assign to type.name for types you create, the effect being kind of like a typedef?)'' | |||
edits