148
edits
(→Properties of types: less bogus example of .ptr.array()) |
|||
| Line 657: | Line 657: | ||
=Future directions= | =Future directions= | ||
* callbacks (JITting native wrappers that conform to a given C/C++ function-pointer type and call a JS function. Finding the right cx to use will be tricky.) | * callbacks (JITting native wrappers that conform to a given C/C++ function-pointer type and call a JS function. Finding the right cx to use will be tricky.) | ||
=Implementation notes= | |||
'''The ctypes instance.''' Currently, via ctypes.jsm, we instantiate a fresh ctypes instance each time the module is imported - the global 'ctypes' property will be a different object each time. This doesn't matter right now, because ctypes doesn't have any prototype objects of its own - just object constants and functions. With the API proposal above, it will have a CType object that serves as prototype for the other types. With this in mind, do we want to have 1) a single ctypes instance, which we stash in a C++ static global and hand out on demand; or 2) a separate ctypes instance per import? | |||
* With 1), I'm not sure if there would be issues with having a single ctypes object span multiple JSRuntimes or somesuch. If so, we might be stuck. If not, we will need to carefully seal the ctypes object and its children, and it won't be able to have a __parent__. Threadsafety should be trivial; at most we will need to make the ctypes init function safe against reentrance. | |||
* With 2), we will have different CType proto objects per ctypes instance. Will this be an issue for code wanting to pass ctypes objects between module instances? ctypes does not internally depend on prototype object equality, only on JSClass equality, so it will work. Consumers will have trouble if they want to compare prototype objects, however. I'm not sure if this is a big deal. Also, doing this means that we need to stash the CType proto object somewhere, so it's accessible from C++. I don't think we can depend on having the 'ctypes' object hanging off the global object - unless we make it readonly - in which case we need to have the CType proto object hanging off each object we create. (Which we should get for free, as long as all the type object __proto__'s are readonly!) So, either we make the 'ctypes' property readonly, or we make {every type object}.__proto__ readonly, or both. | |||
'''Arrays as function arguments.''' When declaring arrays as part of a struct, union, or another array in C, the data is inline. When passing as a function argument, however, they are passed by pointer. Further, C allows implicit type conversion from array to pointer (for the topmost array level). You can't have an array return type in C. Thus we have two options. | |||
* 1) Forbid function declarations with arrays as parameter types. What you really mean by <code>void foo(char c[8]);</code> is <code>void foo(char* c);</code>, so the ctypes declaration could look like <code>const foo = ctypes.declare(..., ctypes.char.array(8).ptr);</code> and at call time you would pass the array by <code>array.address()</code>. (If you actually want to pass an array by value, stick it in a struct first, just like in C.) | |||
* 2) Have things magically convert. There are two parts to this. | |||
** a) <code>library.declare</code>, when given an ArrayType, automatically does <code>.ptr</code> for you. | |||
** b) <code>ImplicitConvert(val, t)</code> will deal, in the general case. If val is a CData object of ArrayType u, and t is a PointerType whose baseType is an ArrayType v, and <code>SameType(u, v)</code> is true, then return a pointer to the array. | |||
* 3) As above, but have <code>ImplicitConvert</code> only do array -> pointer conversion when converting a parameter for a function call. | |||
:I like 2), because it's most consistent with C. | |||
edits