638
edits
| Line 102: | Line 102: | ||
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. | 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. | ||
=== | === Built-in types === | ||
ctypes provides the following | ctypes provides the following types: | ||
:'''<code>ctypes.int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float32_t, float64_t</code>''' - Primitive numeric 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 | :'''<code>ctypes.int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float32_t, float64_t</code>''' - Primitive numeric 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 a limit to what we can realistically do about it). | ||
:'''<code>ctypes.size_t, ssize_t, intptr_t, uintptr_t</code>''' - Primitive types whose size depends on the platform. These types do not autoconvert to JavaScript numbers because on some platforms, there are values of these types that cannot be precisely represented as a JS number. | |||
:''(Open issue: Operator overloading will eventually come to JS. JS will likely have a 64-bit integer object type someday. The above non-autoconverting behavior prevents us from later autoconverting these CTypes to 64-bit values.)'' | |||
:'''<code>ctypes.bool, short, unsigned_short, int, unsigned, unsigned_int, long, unsigned_long, float, double</code>''' - 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, <code>unsigned</code> is always an alias for <code>unsigned_int</code>. | :'''<code>ctypes.bool, short, unsigned_short, int, unsigned, unsigned_int, long, unsigned_long, float, double</code>''' - 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, <code>unsigned</code> is always an alias for <code>unsigned_int</code>. | ||
:''(Open issue: Does <code>long</code> autoconvert to a JS number?)'' | |||
:'''<code>ctypes.char, ctypes.signed_char, ctypes.unsigned_char</code>''' - Character types that behave like the corresponding C types. (These are distinct from <code>int8_t</code> and <code>uint8_t</code> in details of conversion behavior. For example, js-ctypes autoconverts between C characters and one-character JavaScript strings.) | :'''<code>ctypes.char, ctypes.signed_char, ctypes.unsigned_char</code>''' - Character types that behave like the corresponding C types. (These are distinct from <code>int8_t</code> and <code>uint8_t</code> in details of conversion behavior. For example, js-ctypes autoconverts between C characters and one-character JavaScript strings.) | ||
| Line 182: | Line 188: | ||
Minutiae: | Minutiae: | ||
:The <nowiki>[[Class]]</nowiki> of a ctypes type is <code>" | :'''<code>ctypes.CType</code>''' is the abstract-base-class constructor of all js-ctypes types. If called, it throws a <code>TypeError</code>. (This is exposed in order to expose <code>ctypes.CType.prototype</code>.) | ||
:The <nowiki>[[Class]]</nowiki> of a ctypes type is <code>"CType"</code>. | |||
:The <nowiki>[[Class]]</nowiki> of the type constructors <code>ctypes.{C,Array,Struct,Pointer}Type</code> is <code>"Function"</code>. | |||
:Every | :Every <code>CType</code> has a read-only, permanent <code>.prototype</code> property. The type-constructors <code>ctypes.{C,Pointer,Struct,Array}Type</code> each have a read-only, permanent <code>.prototype</code> property as well. | ||
:Types have a hierarchy of prototype objects. The prototype of <code>ctypes. | :Types have a hierarchy of prototype objects. The prototype of <code>ctypes.CType.prototype</code> is <code>Function.prototype</code>. The prototype of <code>ctypes.{Array,Struct,Pointer}Type.prototype</code> and of all the builtin types except for the string types and <code>ctypes.voidptr_t</code> is <code>ctypes.CType.prototype</code>. The prototype of an array type is <code>ctypes.ArrayType.prototype</code>. The prototype of a struct type is <code>ctypes.StructType.prototype</code>. The prototype of a string type or pointer type is <code>ctypes.PointerType.prototype</code>. | ||
:Every | :Every <code>CType</code> ''t'' has <code>''t''.prototype.constructor === ''t''</code>; that is, its <code>.prototype</code> has a read-only, permanent, own <code>.constructor</code> property that refers to the type. The same is true of the four type constructors <code>ctypes.{C,Array,Struct,Pointer}Type</code>. | ||
=== Calling types === | === Calling types === | ||
<code>CType</code>s are JavaScript constructors. That is, they are functions, and they can be called in various different ways. (<code>CData</code> objects are described in a separate section, below.) | |||
:'''<code>new ''t''</code>''' or '''<code>new ''t''()</code>''' or '''<code>''t''()</code>''' - Create a new <code>CData</code> object of type ''t''. | |||
: | :Without arguments, these allocate a new buffer of <code>''t''.size</code> bytes, populate it with zeroes, and return a new <code>CData</code> object referring to the complete object in that buffer. | ||
:If <code>''t''.size</code> is <code>undefined</code>, this throws a <code>TypeError</code>. | :If <code>''t''.size</code> is <code>undefined</code>, this throws a <code>TypeError</code>. | ||
:'''<code>''t''()</code>''' | :'''<code>new ''t''(''val'')</code>''' or '''<code>''t''(''val'')</code> - Convert ''val'' to type ''t'' according to the explicit conversion rules below, throwing a <code>TypeError</code> if the conversion is impossible. Allocate a new buffer of <code>''t''.size</code> bytes, populated with the converted value. Return a new <code>CData</code> object of type ''t'' referring to the complete object in that buffer. (When ''val'' is a <code>CData</code> object of type ''t'', the behavior is like <code>malloc</code> followed by <code>memcpy</code>.) | ||
:'''<code> | :As a special case, if ''t'' is an array type of unspecified length and <code>typeof ''val''</code> is <code>'number'</code> and ''val'' is a nonnegative integer, allocate a new buffer of size <code>''val'' * ''t''.elementType.size</code>. Populate it with zeroes. Return a <code>CData</code> object of type ''t'' referring to the new array. | ||
== CData objects == | |||
A <code>CData</code> object represents a C/C++ value located in memory. The address of the C/C++ value can be taken, and it can be assigned to. | |||
It is possible for multiple <code>CData</code> objects to refer to the same memory. (In this way they are sort of like C++ references, but the syntax is quite different.) | |||
''(TODO)'' | ''(TODO)'' | ||
:'''<code>'' | :'''<code>''cdata''.assign(''val'')</code>''' - Convert ''val'' to the type of ''cdata'' using the implicit conversion rules. Store the converted value in the buffer location referred to by ''cdata''. | ||
:'''<code>'' | :'''<code>''cdata''.constructor</code>''' - Read-only. The type of ''cdata''. ''(Implementation note: The prototype of ''cdata'' is an object that has a read-only <code>constructor</code> property, as detailed under "minutiae".)'' | ||
<code>CData</code> objects of struct types have getters and setters for each struct member: | |||
:'''<code>''cstruct''.''member''</code>''' - Let '' | :'''<code>''cstruct''.''member''</code>''' - Let ''F'' be a <code>CData</code> object referring to the struct member. Return <code>ConvertToJS(''F'')</code>. | ||
:'''<code>''cstruct''.''member'' = ''value''</code>''' - The value is converted to the type of the member using the implicit conversion rules. The converted value is stored in the buffer. | :'''<code>''cstruct''.''member'' = ''value''</code>''' - The value is converted to the type of the member using the implicit conversion rules. The converted value is stored in the buffer. | ||
These getters and setters can shadow the properties and methods described above. | These getters and setters can shadow the properties and methods described above. ''(Open issue: Can they really shadow <code>.constructor</code>? Maybe <code>StructType</code> should shoot you down if you try that one.)'' | ||
Likewise, array | Likewise, <code>CData</code> objects of array types have getters and setters for each element. Arrays additionally have a <code>length</code> property. | ||
Note that these getters and setters are only present for integers ''i'' in the range 0 ≤ i < <code>''carray''.length</code>. ''(Open issue: can we arrange to throw an exception if ''i'' is out of range?)'' | Note that these getters and setters are only present for integers ''i'' in the range 0 ≤ i < <code>''carray''.length</code>. ''(Open issue: can we arrange to throw an exception if ''i'' is out of range?)'' | ||
:'''<code>''carray''[''i'']</code>''' - Let '' | :'''<code>''carray''[''i'']</code>''' - Let ''E'' be a <code>CData</code> object referring to the element at index ''i''. Return <code>ConvertToJS(''R'')</code>. | ||
:'''<code>''carray''[''i''] = ''val''</code>''' - Convert ''val'' to the type of the array element using the implicit conversion rules and store the result in the buffer. | :'''<code>''carray''[''i''] = ''val''</code>''' - Convert ''val'' to the type of the array element using the implicit conversion rules and store the result in the buffer. | ||
:'''<code>''carray''.length</code>''' - Read-only. The length of the array. | :'''<code>''carray''.length</code>''' - Read-only. The length of the array. | ||
''(Open issue: Do we care about arrays eventually having a length longer than 2<sup>53</sup>, i.e. not representable as a JS number? It's currently impossible even on 64-bit platforms.)'' | |||
''(TODO: Figure out if the type of <code>new FooArray(30)</code> is <code>FooArray</code> or <code>ArrayType(Foo, 30)</code>.)'' | ''(TODO: Figure out if the type of <code>new FooArray(30)</code> is <code>FooArray</code> or <code>ArrayType(Foo, 30)</code>.)'' | ||
''(TODO: Possibly, a way to get a | ''(TODO: Possibly, a way to get a <code>CData</code> object that acts like a view on a window of an array. E.g. ''carray''.slice(start, stop). Then you could <code>.assign</code> one region of memory to another, effectively memcpy-ing.)'' | ||
''(TODO: Pointer types might need some properties of their own.)'' | |||
Minutiae: | Minutiae: | ||
:The <nowiki>[[Class]]</nowiki> of a | :The <nowiki>[[Class]]</nowiki> of a <code>CData</code> object is <code>"CData"</code>. | ||
:The prototype of a | :The prototype of a <code>CData</code> object is the same as its type's <code>.prototype</code> property. | ||
''(Implementation notes: A | ''(Implementation notes: A <code>CData</code> object has a reserved slot that points to its type; a reserved slot that points to the base <code>CData</code> object that owns the backing buffer where the data is stored, or <code>null</code> if the object owns its own buffer; and a pointer to the actual referenced location within the buffer. Since the data pointer might not be aligned to 2 bytes, PRIVATE_TO_JSVAL is insufficient; a custom JSClass.trace hook will be needed. If the object owns its own buffer, its finalizer frees it; other <code>CData</code> objects that point into the buffer keep the buffer alive, thanks to the reserved slot.)'' | ||
== Pointers == | == Pointers == | ||
''(TODO - this needs an overhaul! please disregard it for now!)'' | |||
js-ctypes pointers are very simple JavaScript objects that represent C/C++ pointers. Like C/C++ pointers, js-ctypes pointers represent a memory address. They may point to valid memory, but they may also point off the end of an array, to memory that has been freed, to uninitialized or unmapped memory, or to data of a different type. | js-ctypes pointers are very simple JavaScript objects that represent C/C++ pointers. Like C/C++ pointers, js-ctypes pointers represent a memory address. They may point to valid memory, but they may also point off the end of an array, to memory that has been freed, to uninitialized or unmapped memory, or to data of a different type. | ||
edits