From 692472e5731b46dfb6d6db2b7a92ebd6f284e23b Mon Sep 17 00:00:00 2001 From: Paul Loyd Date: Thu, 29 Aug 2013 23:26:21 +0400 Subject: [PATCH 1/8] Add "ref" module --- node-ffi/node-ffi-tests.ts | 18 +++ node-ffi/node-ffi.d.ts | 249 +++++++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 node-ffi/node-ffi-tests.ts create mode 100644 node-ffi/node-ffi.d.ts diff --git a/node-ffi/node-ffi-tests.ts b/node-ffi/node-ffi-tests.ts new file mode 100644 index 000000000..aba1f708d --- /dev/null +++ b/node-ffi/node-ffi-tests.ts @@ -0,0 +1,18 @@ +/// + +import ref = require('ref'); + +ref.address(new Buffer(1)); +var intBuf = ref.alloc(ref.types.int); +var intWith4 = ref.alloc(ref.types.int, 4); +var buf0 = ref.allocCString('hello world'); +var type = ref.coerceType('int **'); +var val = ref.deref(intBuf); +ref.isNull(new Buffer(1)); +var str = ref.readCString(new Buffer('hello\0world\0'), 0); +var buf1 = ref.alloc('int64'); +ref.writeInt64BE(buf1, 0, '9223372036854775807'); +var val = ref.readInt64BE(buf1, 0) +var voidPtrType = ref.refType(ref.types.void); +var buf2 = ref.alloc('int64'); +ref.writeInt64LE(buf2, 0, '9223372036854775807'); diff --git a/node-ffi/node-ffi.d.ts b/node-ffi/node-ffi.d.ts new file mode 100644 index 000000000..2b6485fb2 --- /dev/null +++ b/node-ffi/node-ffi.d.ts @@ -0,0 +1,249 @@ +// Type definitions for node-ffi, ref, ref-array, ref-struct and ref-union +// Project: https://github.com/rbranson/node-ffi +// Definitions by: Paul Loyd +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +/// + +declare module "ffi" {} + +declare module "ref" { + export interface Type { + /** The size in bytes required to hold this datatype. */ + size: number; + /** The current level of indirection of the buffer. */ + indirection: number; + /** To invoke when ref.get() is invoked on a buffer of this type. */ + get(buffer: NodeBuffer, offset: number): any; + /** To invoke when ref.set() is invoked on a buffer of this type. */ + set(buffer: NodeBuffer, offset: number, value): void; + /** The name to use during debugging for this datatype. */ + name?: string; + /** The alignment of this datatype when placed inside a struct. */ + alignment?: number; + } + + /** A Buffer that references the C NULL pointer. */ + export var NULL: NodeBuffer; + /** A pointer-sized Buffer instance pointing to NULL. */ + export var NULL_POINTER: NodeBuffer; + /** Get the memory address of buffer. */ + export function address(buffer: NodeBuffer): number; + /** Allocate the memory with the given value written to it. */ + export function alloc(type: Type, value?): NodeBuffer; + /** Allocate the memory with the given value written to it. */ + export function alloc(type: string, value?): NodeBuffer; + + /** + * Allocate the memory with the given string written to it with the given + * encoding (defaults to utf8). The buffer is 1 byte longer than the + * string itself, and is NULL terminated. + */ + export function allocCString(string: string, encoding?: string): NodeBuffer; + + /** Coerce a type.*/ + export function coerceType(type: Type): Type; + /** Coerce a type. String are looked up from the ref.types object. */ + export function coerceType(type: string): Type; + + /** + * Get value after dereferencing buffer. + * That is, first it checks the indirection count of buffer's type, and + * if it's greater than 1 then it merely returns another Buffer, but with + * one level less indirection. + */ + export function deref(buffer: NodeBuffer): any; + + /** Create clone of the type, with decremented indirection level by 1. */ + export function derefType(type: Type): Type; + /** Create clone of the type, with decremented indirection level by 1. */ + export function derefType(type: string): Type; + /** Represents the native endianness of the processor ("LE" or "BE"). */ + export var endianness: string; + /** Check the indirection level and return a dereferenced when necessary. */ + export function get(buffer: NodeBuffer, offset?: number, type?: Type): any; + /** Check the indirection level and return a dereferenced when necessary. */ + export function get(buffer: NodeBuffer, offset?: number, type?: string): any; + /** Get type of the buffer. Create a default type when none exists. */ + export function getType(buffer: NodeBuffer): Type; + /** Check the NULL. */ + export function isNull(buffer: NodeBuffer): boolean; + /** Read C string until the first NULL. */ + export function readCString(buffer: NodeBuffer, offset?: number): string; + + /** + * Read a big-endian signed 64-bit int + * If there is losing precision, then return a string, otherwise a number. + * @return {number|string} + */ + export function readInt64BE(buffer: NodeBuffer, offset?: number): any; + + /** + * Read a little-endian signed 64-bit int + * If there is losing precision, then return a string, otherwise a number. + * @return {number|string} + */ + export function readInt64LE(buffer: NodeBuffer, offset?: number): any; + + /** Read a JS Object that has previously been written. */ + export function readObject(buffer: NodeBuffer, offset?: number): Object; + /** Read data from the pointer. */ + export function readPointer(buffer: NodeBuffer, offset?: number, + length?: number): NodeBuffer; + /** + * Read a big-endian unsigned 64-bit int + * If there is losing precision, then return a string, otherwise a number. + * @return {number|string} + */ + export function readUInt64BE(buffer: NodeBuffer, offset?: number): any; + + /** + * Read a little-endian unsigned 64-bit int + * If there is losing precision, then return a string, otherwise a number. + * @return {number|string} + */ + export function readUInt64LE(buffer: NodeBuffer, offset?: number): any; + + /** Create pointer to buffer. */ + export function ref(buffer: NodeBuffer): NodeBuffer; + /** Create clone of the type, with incremented indirection level by 1. */ + export function refType(type: Type): Type; + /** Create clone of the type, with incremented indirection level by 1. */ + export function refType(type: string): Type; + + /** + * Create buffer with the specified size, with the same address as source. + * This function "attaches" source to the returned buffer to prevent it from + * being garbage collected. + */ + export function reinterpret(buffer: NodeBuffer, size: number, + offset?: number): NodeBuffer; + /** + * Scan past the boundary of the Buffer's length until it finds size number + * of aligned NULL bytes. + */ + export function reinterpretUntilZeros(buffer: NodeBuffer, size: number, + offset?: number): NodeBuffer; + + /** Write pointer if the indirection is 1, otherwise write value. */ + export function set(buffer: NodeBuffer, offset: number, value, type?: Type): void; + /** Write pointer if the indirection is 1, otherwise write value. */ + export function set(buffer: NodeBuffer, offset: number, value, type?: string): void; + /** Write the string as a NULL terminated. Default encoding is utf8. */ + export function writeCString(buffer: NodeBuffer, offset: number, + string: string, encoding?: string): void; + /** Write a big-endian signed 64-bit int. */ + export function writeInt64BE(buffer: NodeBuffer, offset: number, input: number): void; + /** Write a big-endian signed 64-bit int. */ + export function writeInt64BE(buffer: NodeBuffer, offset: number, input: string): void; + /** Write a little-endian signed 64-bit int. */ + export function writeInt64LE(buffer: NodeBuffer, offset: number, input: number): void; + /** Write a little-endian signed 64-bit int. */ + export function writeInt64LE(buffer: NodeBuffer, offset: number, input: string): void; + + /** + * Write the JS Object. This function "attaches" object to buffer to prevent + * it from being garbage collected. + */ + export function writeObject(buffer: NodeBuffer, offset: number, object: Object): void; + + /** + * Write the memory address of pointer to buffer at the specified offset. This + * function "attaches" object to buffer to prevent it from being garbage collected. + */ + export function writePointer(buffer: NodeBuffer, offset: number, + pointer: NodeBuffer): void; + + /** Write a little-endian unsigned 64-bit int. */ + export function writeUInt64BE(buffer: NodeBuffer, offset: number, input: number): void; + /** Write a little-endian unsigned 64-bit int. */ + export function writeUInt64BE(buffer: NodeBuffer, offset: number, input: string): void; + + /** + * Attach object to buffer such. + * It prevents object from being garbage collected until buffer does. + */ + export function _attach(buffer: NodeBuffer, object: Object); + + /** Same as ref.reinterpret, except that this version does not attach buffer. */ + export function _reinterpret(buffer: NodeBuffer, size: number, + offset?: number): NodeBuffer; + /** Same as ref.reinterpretUntilZeros, except that this version does not attach buffer. */ + export function _reinterpretUntilZeros(buffer: NodeBuffer, size: number, + offset?: number): NodeBuffer; + /** Same as ref.writePointer, except that this version does not attach pointer. */ + export function _writePointer(buffer: NodeBuffer, offset: number, + pointer: NodeBuffer): void; + /** Same as ref.writeObject, except that this version does not attach object. */ + export function _writeObject(buffer: NodeBuffer, offset: number, object: Object): void; + + export var types: { + void: Type; int64: Type; ushort: Type; + int: Type; uint64: Type; float: Type; + uint: Type; long: Type; double: Type; + int8: Type; ulong: Type; Object: Type; + uint8: Type; longlong: Type; CString: Type; + int16: Type; ulonglong: Type; bool: Type; + uint16: Type; char: Type; byte: Type; + int32: Type; uchar: Type; size_t: Type; + uint32: Type; short: Type; + }; +} + +interface NodeBuffer { + /** Shorthand for ref.address. */ + address(): number; + /** Shorthand for ref.deref. */ + deref(): any; + /** Shorthand for ref.isNull. */ + isNull(): boolean; + /** Shorthand for ref.readCString. */ + readCString(offset?: number): string; + /** Shorthand for ref.readInt64BE. */ + readInt64BE(offset?: number): string; + /** Shorthand for ref.readInt64LE. */ + readInt64LE(offset?: number): string; + /** Shorthand for ref.readObject. */ + readObject(offset?: number): string; + /** Shorthand for ref.readPointer. */ + readPointer(offset?: number): string; + /** Shorthand for ref.readUInt64BE. */ + readUInt64BE(offset?: number): string; + /** Shorthand for ref.readUInt64LE. */ + readUInt64LE(offset?: number): string; + /** Shorthand for ref.ref. */ + ref(): NodeBuffer; + /** Shorthand for ref.reinterpret. */ + reinterpret(size: number, offset?: number): NodeBuffer; + /** Shorthand for ref.reinterpretUntilZeros. */ + reinterpretUntilZeros(size: number, offset?: number): NodeBuffer; + /** Shorthand for ref.writeCString. */ + writeCString(offset: number, string: string, encoding?: string): void; + /** Shorthand for ref.writeInt64BE. */ + writeInt64BE(offset: number, input: number): any; + /** Shorthand for ref.writeInt64BE. */ + writeInt64BE(offset: number, input: string): any; + /** Shorthand for ref.writeInt64LE. */ + writeInt64LE(offset: number, input: number): any; + /** Shorthand for ref.writeInt64LE. */ + writeInt64LE(offset: number, input: string): any; + /** Shorthand for ref.writeObject. */ + writeObject(offset: number, object: Object): void; + /** Shorthand for ref.writePointer. */ + writePointer(offset: number, pointer: NodeBuffer): void; + /** Shorthand for ref.writeUInt64BE. */ + writeUInt64BE(offset: number, input: number): any; + /** Shorthand for ref.writeUInt64BE. */ + writeUInt64BE(offset: number, input: string): any; + /** Shorthand for ref.writeUInt64LE. */ + writeUInt64LE(offset: number, input: number): any; + /** Shorthand for ref.writeUInt64LE. */ + writeUInt64LE(offset: number, input: string): any; + + /** + * Generate string for inspecting. + * String includes the hex-encoded memory address of the Buffer instance. + * @override + */ + inspect(): string; +} From 6d31303c4d85130b8dfb5d27e21cb22f4bdc2cef Mon Sep 17 00:00:00 2001 From: Paul Loyd Date: Sat, 7 Sep 2013 00:57:40 +0400 Subject: [PATCH 2/8] Add "ffi" module --- node-ffi/node-ffi-tests.ts | 66 ++++++-- node-ffi/node-ffi.d.ts | 305 ++++++++++++++++++++++++++++++------- 2 files changed, 304 insertions(+), 67 deletions(-) diff --git a/node-ffi/node-ffi-tests.ts b/node-ffi/node-ffi-tests.ts index aba1f708d..a29d8dbd6 100644 --- a/node-ffi/node-ffi-tests.ts +++ b/node-ffi/node-ffi-tests.ts @@ -1,18 +1,56 @@ /// +import ffi = require('ffi'); import ref = require('ref'); -ref.address(new Buffer(1)); -var intBuf = ref.alloc(ref.types.int); -var intWith4 = ref.alloc(ref.types.int, 4); -var buf0 = ref.allocCString('hello world'); -var type = ref.coerceType('int **'); -var val = ref.deref(intBuf); -ref.isNull(new Buffer(1)); -var str = ref.readCString(new Buffer('hello\0world\0'), 0); -var buf1 = ref.alloc('int64'); -ref.writeInt64BE(buf1, 0, '9223372036854775807'); -var val = ref.readInt64BE(buf1, 0) -var voidPtrType = ref.refType(ref.types.void); -var buf2 = ref.alloc('int64'); -ref.writeInt64LE(buf2, 0, '9223372036854775807'); +{ + var sqlite3 = ref.types.void; + var sqlite3Ptr = ref.refType(sqlite3); + var sqlite3PtrPtr = ref.refType(sqlite3Ptr); + var stringPtr = ref.refType(ref.types.CString); + + var libsqlite3 = ffi.Library('libsqlite3', { + 'sqlite3_open': [ 'int', [ 'string', sqlite3PtrPtr ] ], + 'sqlite3_close': [ 'int', [ sqlite3PtrPtr ] ], + 'sqlite3_exec': [ 'int', [ sqlite3PtrPtr, 'string', 'pointer', 'pointer', stringPtr ] ], + 'sqlite3_changes': [ 'int', [ sqlite3PtrPtr ]] + }); + + var dbPtrPtr = ref.alloc(sqlite3PtrPtr); + libsqlite3.sqlite3_open("test.sqlite3", dbPtrPtr); + var dbHandle = dbPtrPtr.deref(); +} +{ + var func = ffi.ForeignFunction(new Buffer(10), 'int', [ 'int' ]); + func(-5); + func.async(-5, function(err, res) {}); +} +{ + var printfPointer = ffi.DynamicLibrary().get('printf'); + var printfGen = ffi.VariadicForeignFunction(printfPointer, 'void', [ 'string' ]); + printfGen()('Hello World!\n'); + printfGen('int')('This is an int: %d\n', 10); + printfGen('string')('This is a string: %s\n', 'hello'); +} +{ + ref.address(new Buffer(1)); + var intBuf = ref.alloc(ref.types.int); + var intWith4 = ref.alloc(ref.types.int, 4); + var buf0 = ref.allocCString('hello world'); + var type = ref.coerceType('int **'); + var val = ref.deref(intBuf); +} +{ + ref.isNull(new Buffer(1)); +} +{ + var str = ref.readCString(new Buffer('hello\0world\0'), 0); + var buf = ref.alloc('int64'); + ref.writeInt64BE(buf, 0, '9223372036854775807'); + var val = ref.readInt64BE(buf, 0) +} +{ + var voidPtrType = ref.refType(ref.types.void); + var buf = ref.alloc('int64'); + ref.writeInt64LE(buf, 0, '9223372036854775807'); +} diff --git a/node-ffi/node-ffi.d.ts b/node-ffi/node-ffi.d.ts index 2b6485fb2..7c94cc761 100644 --- a/node-ffi/node-ffi.d.ts +++ b/node-ffi/node-ffi.d.ts @@ -5,17 +5,19 @@ /// -declare module "ffi" {} +declare module "ffi" { + // import StructType = require('ref-struct'); + + export interface StructType {} -declare module "ref" { export interface Type { /** The size in bytes required to hold this datatype. */ size: number; /** The current level of indirection of the buffer. */ indirection: number; - /** To invoke when ref.get() is invoked on a buffer of this type. */ + /** To invoke when `ref.get` is invoked on a buffer of this type. */ get(buffer: NodeBuffer, offset: number): any; - /** To invoke when ref.set() is invoked on a buffer of this type. */ + /** To invoke when `ref.set` is invoked on a buffer of this type. */ set(buffer: NodeBuffer, offset: number, value): void; /** The name to use during debugging for this datatype. */ name?: string; @@ -23,14 +25,210 @@ declare module "ref" { alignment?: number; } + /** Provides a friendly API on-top of `DynamicLibrary` and `ForeignFunction`. */ + export var Library: { + /** The extension to use on libraries. */ + EXT: string; + + /** + * @param libFile name of library + * @param funcs hash of [retType, [...argType], opts?: {abi?, async?, varargs?}] + * @param lib hash that will be extended + */ + new (libFile: string, funcs?: {[key: string]: any[]}, lib?: Object): any; + + /** + * @param libFile name of library + * @param funcs hash of [retType, [...argType], opts?: {abi?, async?, varargs?}] + * @param lib hash that will be extended + */ + (libFile: string, funcs?: {[key: string]: any[]}, lib?: Object): any; + }; + + /** Get value of errno. */ + export function errno(): number; + + export interface Function extends Type { + /** The type of return value. */ + retType: Type; + /** The type of arguments. */ + argTypes: Type[]; + abi: number; + + /** Is set for node-ffi functions. */ + ffi_type: NodeBuffer; + /** The size in bytes required to hold this datatype. */ + size: number; + /** The current level of indirection of the buffer. */ + indirection: number; + /** To invoke when `ref.get` is invoked on a buffer of this type. */ + get(buffer: NodeBuffer, offset: number): any; + /** To invoke when `ref.set` is invoked on a buffer of this type. */ + set(buffer: NodeBuffer, offset: number, value): void; + /** The alignment of this datatype when placed inside a struct. */ + alignment: number; + + /** Get a `Callback` pointer of this function type. */ + toPointer(fn: (...args: any[]) => any): NodeBuffer; + /** Get a `ForeignFunction` of this function type. */ + toFunction(buf: NodeBuffer): ForeignFunction; + } + + /** Creates and returns a type for a C function pointer. */ + export var Function: { + new (retType: Type, argTypes: any[], abi?: number): Function; + new (retType: string, argTypes: any[], abi?: number): Function; + (retType: Type, argTypes: any[], abi?: number): Function; + (retType: string, argTypes: any[], abi?: number): Function; + }; + + export interface ForeignFunction { + (...args: any[]): any; + async(...args: any[]): void; + } + + /** + * Represents a foreign function in another library. Manages all of the aspects + * of function execution, including marshalling the data parameters for the + * function into native types and also unmarshalling the return from function + * execution. + */ + export var ForeignFunction: { + new (ptr: NodeBuffer, retType: Type, argTypes: any[], abi?: number): ForeignFunction; + new (ptr: NodeBuffer, retType: string, argTypes: any[], abi?: number): ForeignFunction; + (ptr: NodeBuffer, retType: Type, argTypes: any[], abi?: number): ForeignFunction; + (ptr: NodeBuffer, retType: string, argTypes: any[], abi?: number): ForeignFunction; + } + + export interface VariadicForeignFunction { + /** + * What gets returned is another function that needs to be invoked with the rest + * of the variadic types that are being invoked from the function. + */ + (...args: any[]): ForeignFunction; + + /** + * Return type as a property of the function generator to + * allow for monkey patching the return value in the very rare case where the + * return type is variadic as well + */ + returnType: any; + } + + /** + * For when you want to call to a C function with variable amount of arguments. + * i.e. `printf`. + * + * This function takes care of caching and reusing `ForeignFunction` instances that + * contain the same ffi_type argument signature. + */ + export var VariadicForeignFunction: { + new (ptr: NodeBuffer, ret: Type, fixedArgs: any[], abi?: number): VariadicForeignFunction; + new (ptr: NodeBuffer, ret: string, fixedArgs: any[], abi?: number): VariadicForeignFunction; + (ptr: NodeBuffer, ret: Type, fixedArgs: any[], abi?: number): VariadicForeignFunction; + (ptr: NodeBuffer, ret: string, fixedArgs: any[], abi?: number): VariadicForeignFunction; + }; + + export interface DynamicLibrary { + /** Close library, returns the result of the `dlclose` system function. */ + close(): number; + /** Get a symbol from this library. */ + get(symbol: string): NodeBuffer; + /** Get the result of the `dlerror` system function. */ + error(): string; + } + + /** + * This class loads and fetches function pointers for dynamic libraries + * (.so, .dylib, etc). After the libray's function pointer is acquired, then you + * call `get(symbol)` to retreive a pointer to an exported symbol. You need to + * call `get___` on the pointer to dereference it into its actual value, or + * turn the pointer into a callable function with `ForeignFunction`. + */ + export var DynamicLibrary: { + FLAGS: { + RTLD_LAZY: number; + RTLD_NOW: number; + RTLD_LOCAL: number; + RTLD_GLOBAL: number; + RTLD_NOLOAD: number; + RTLD_NODELETE: number; + RTLD_NEXT: NodeBuffer; + RTLD_DEFAUL: NodeBuffer; + } + + new (path?: string, mode?: number): DynamicLibrary; + (path?: string, mode?: number): DynamicLibrary; + }; + + /** + * Turns a JavaScript function into a C function pointer. + * The function pointer may be used in other C functions that + * accept C callback functions. + */ + export var Callback: { + new (retType, argTypes: any[], abi: number, fn: Function): NodeBuffer; + new (retType, argTypes: any[], fn: Function): NodeBuffer; + (retType, argTypes: any[], abi: number, fn: Function): NodeBuffer; + (retType, argTypes: any[], fn: Function): NodeBuffer; + } + + export var ffiType: { + /** Get a `ffi_type *` Buffer appropriate for the given type. */ + (type: Type): NodeBuffer + /** Get a `ffi_type *` Buffer appropriate for the given type. */ + (type: string): NodeBuffer + FFI_TYPE: StructType; + } + + export var CIF: Function; + export var CIF_var: Function; + export var HAS_OBJC: boolean; + export var FFI_TYPES: {[key: string]: NodeBuffer}; + export var FFI_OK: number; + export var FFI_BAD_TYPEDEF: number; + export var FFI_BAD_ABI: number; + export var FFI_DEFAULT_ABI: number; + export var FFI_FIRST_ABI: number; + export var FFI_LAST_ABI: number; + export var FFI_SYSV: number; + export var FFI_UNIX64: number; + export var RTLD_LAZY: number; + export var RTLD_NOW: number; + export var RTLD_LOCAL: number; + export var RTLD_GLOBAL: number; + export var RTLD_NOLOAD: number; + export var RTLD_NODELETE: number; + export var RTLD_NEXT: NodeBuffer; + export var RTLD_DEFAULT: NodeBuffer; + export var LIB_EXT: string; + export var FFI_TYPE: StructType; + + /** Default types. */ + export var types: { + void: Type; int64: Type; ushort: Type; + int: Type; uint64: Type; float: Type; + uint: Type; long: Type; double: Type; + int8: Type; ulong: Type; Object: Type; + uint8: Type; longlong: Type; CString: Type; + int16: Type; ulonglong: Type; bool: Type; + uint16: Type; char: Type; byte: Type; + int32: Type; uchar: Type; size_t: Type; + uint32: Type; short: Type; + }; +} + +declare module "ref" { + import ffi = require('ffi'); + /** A Buffer that references the C NULL pointer. */ export var NULL: NodeBuffer; - /** A pointer-sized Buffer instance pointing to NULL. */ + /** A pointer-sized buffer pointing to NULL. */ export var NULL_POINTER: NodeBuffer; /** Get the memory address of buffer. */ export function address(buffer: NodeBuffer): number; /** Allocate the memory with the given value written to it. */ - export function alloc(type: Type, value?): NodeBuffer; + export function alloc(type: ffi.Type, value?): NodeBuffer; /** Allocate the memory with the given value written to it. */ export function alloc(type: string, value?): NodeBuffer; @@ -42,9 +240,9 @@ declare module "ref" { export function allocCString(string: string, encoding?: string): NodeBuffer; /** Coerce a type.*/ - export function coerceType(type: Type): Type; + export function coerceType(type: ffi.Type): ffi.Type; /** Coerce a type. String are looked up from the ref.types object. */ - export function coerceType(type: string): Type; + export function coerceType(type: string): ffi.Type; /** * Get value after dereferencing buffer. @@ -55,31 +253,31 @@ declare module "ref" { export function deref(buffer: NodeBuffer): any; /** Create clone of the type, with decremented indirection level by 1. */ - export function derefType(type: Type): Type; + export function derefType(type: ffi.Type): ffi.Type; /** Create clone of the type, with decremented indirection level by 1. */ - export function derefType(type: string): Type; + export function derefType(type: string): ffi.Type; /** Represents the native endianness of the processor ("LE" or "BE"). */ export var endianness: string; /** Check the indirection level and return a dereferenced when necessary. */ - export function get(buffer: NodeBuffer, offset?: number, type?: Type): any; + export function get(buffer: NodeBuffer, offset?: number, type?: ffi.Type): any; /** Check the indirection level and return a dereferenced when necessary. */ export function get(buffer: NodeBuffer, offset?: number, type?: string): any; /** Get type of the buffer. Create a default type when none exists. */ - export function getType(buffer: NodeBuffer): Type; + export function getType(buffer: NodeBuffer): ffi.Type; /** Check the NULL. */ export function isNull(buffer: NodeBuffer): boolean; /** Read C string until the first NULL. */ export function readCString(buffer: NodeBuffer, offset?: number): string; /** - * Read a big-endian signed 64-bit int + * Read a big-endian signed 64-bit int. * If there is losing precision, then return a string, otherwise a number. * @return {number|string} */ export function readInt64BE(buffer: NodeBuffer, offset?: number): any; /** - * Read a little-endian signed 64-bit int + * Read a little-endian signed 64-bit int. * If there is losing precision, then return a string, otherwise a number. * @return {number|string} */ @@ -91,14 +289,14 @@ declare module "ref" { export function readPointer(buffer: NodeBuffer, offset?: number, length?: number): NodeBuffer; /** - * Read a big-endian unsigned 64-bit int + * Read a big-endian unsigned 64-bit int. * If there is losing precision, then return a string, otherwise a number. * @return {number|string} */ export function readUInt64BE(buffer: NodeBuffer, offset?: number): any; /** - * Read a little-endian unsigned 64-bit int + * Read a little-endian unsigned 64-bit int. * If there is losing precision, then return a string, otherwise a number. * @return {number|string} */ @@ -107,9 +305,9 @@ declare module "ref" { /** Create pointer to buffer. */ export function ref(buffer: NodeBuffer): NodeBuffer; /** Create clone of the type, with incremented indirection level by 1. */ - export function refType(type: Type): Type; + export function refType(type: ffi.Type): ffi.Type; /** Create clone of the type, with incremented indirection level by 1. */ - export function refType(type: string): Type; + export function refType(type: string): ffi.Type; /** * Create buffer with the specified size, with the same address as source. @@ -119,14 +317,14 @@ declare module "ref" { export function reinterpret(buffer: NodeBuffer, size: number, offset?: number): NodeBuffer; /** - * Scan past the boundary of the Buffer's length until it finds size number + * Scan past the boundary of the buffer's length until it finds size number * of aligned NULL bytes. */ export function reinterpretUntilZeros(buffer: NodeBuffer, size: number, offset?: number): NodeBuffer; /** Write pointer if the indirection is 1, otherwise write value. */ - export function set(buffer: NodeBuffer, offset: number, value, type?: Type): void; + export function set(buffer: NodeBuffer, offset: number, value, type?: ffi.Type): void; /** Write pointer if the indirection is 1, otherwise write value. */ export function set(buffer: NodeBuffer, offset: number, value, type?: string): void; /** Write the string as a NULL terminated. Default encoding is utf8. */ @@ -177,67 +375,68 @@ declare module "ref" { /** Same as ref.writeObject, except that this version does not attach object. */ export function _writeObject(buffer: NodeBuffer, offset: number, object: Object): void; + /** Default types. */ export var types: { - void: Type; int64: Type; ushort: Type; - int: Type; uint64: Type; float: Type; - uint: Type; long: Type; double: Type; - int8: Type; ulong: Type; Object: Type; - uint8: Type; longlong: Type; CString: Type; - int16: Type; ulonglong: Type; bool: Type; - uint16: Type; char: Type; byte: Type; - int32: Type; uchar: Type; size_t: Type; - uint32: Type; short: Type; + void: ffi.Type; int64: ffi.Type; ushort: ffi.Type; + int: ffi.Type; uint64: ffi.Type; float: ffi.Type; + uint: ffi.Type; long: ffi.Type; double: ffi.Type; + int8: ffi.Type; ulong: ffi.Type; Object: ffi.Type; + uint8: ffi.Type; longlong: ffi.Type; CString: ffi.Type; + int16: ffi.Type; ulonglong: ffi.Type; bool: ffi.Type; + uint16: ffi.Type; char: ffi.Type; byte: ffi.Type; + int32: ffi.Type; uchar: ffi.Type; size_t: ffi.Type; + uint32: ffi.Type; short: ffi.Type; }; } interface NodeBuffer { - /** Shorthand for ref.address. */ + /** Shorthand for `ref.address`. */ address(): number; - /** Shorthand for ref.deref. */ + /** Shorthand for `ref.deref`. */ deref(): any; - /** Shorthand for ref.isNull. */ + /** Shorthand for `ref.isNull`. */ isNull(): boolean; - /** Shorthand for ref.readCString. */ + /** Shorthand for `ref.readCString`. */ readCString(offset?: number): string; - /** Shorthand for ref.readInt64BE. */ + /** Shorthand for `ref.readInt64BE`. */ readInt64BE(offset?: number): string; - /** Shorthand for ref.readInt64LE. */ + /** Shorthand for `ref.readInt64LE`. */ readInt64LE(offset?: number): string; - /** Shorthand for ref.readObject. */ + /** Shorthand for `ref.readObject`. */ readObject(offset?: number): string; - /** Shorthand for ref.readPointer. */ + /** Shorthand for `ref.readPointer`. */ readPointer(offset?: number): string; - /** Shorthand for ref.readUInt64BE. */ + /** Shorthand for `ref.readUInt64BE`. */ readUInt64BE(offset?: number): string; - /** Shorthand for ref.readUInt64LE. */ + /** Shorthand for `ref.readUInt64LE`. */ readUInt64LE(offset?: number): string; - /** Shorthand for ref.ref. */ + /** Shorthand for `ref.ref`. */ ref(): NodeBuffer; - /** Shorthand for ref.reinterpret. */ + /** Shorthand for `ref.reinterpret`. */ reinterpret(size: number, offset?: number): NodeBuffer; - /** Shorthand for ref.reinterpretUntilZeros. */ + /** Shorthand for `ref.reinterpretUntilZeros`. */ reinterpretUntilZeros(size: number, offset?: number): NodeBuffer; - /** Shorthand for ref.writeCString. */ + /** Shorthand for `ref.writeCString`. */ writeCString(offset: number, string: string, encoding?: string): void; - /** Shorthand for ref.writeInt64BE. */ + /** Shorthand for `ref.writeInt64BE`. */ writeInt64BE(offset: number, input: number): any; - /** Shorthand for ref.writeInt64BE. */ + /** Shorthand for `ref.writeInt64BE`. */ writeInt64BE(offset: number, input: string): any; - /** Shorthand for ref.writeInt64LE. */ + /** Shorthand for `ref.writeInt64LE`. */ writeInt64LE(offset: number, input: number): any; - /** Shorthand for ref.writeInt64LE. */ + /** Shorthand for `ref.writeInt64LE`. */ writeInt64LE(offset: number, input: string): any; - /** Shorthand for ref.writeObject. */ + /** Shorthand for `ref.writeObject`. */ writeObject(offset: number, object: Object): void; - /** Shorthand for ref.writePointer. */ + /** Shorthand for `ref.writePointer`. */ writePointer(offset: number, pointer: NodeBuffer): void; - /** Shorthand for ref.writeUInt64BE. */ + /** Shorthand for `ref.writeUInt64BE`. */ writeUInt64BE(offset: number, input: number): any; - /** Shorthand for ref.writeUInt64BE. */ + /** Shorthand for `ref.writeUInt64BE`. */ writeUInt64BE(offset: number, input: string): any; - /** Shorthand for ref.writeUInt64LE. */ + /** Shorthand for `ref.writeUInt64LE`. */ writeUInt64LE(offset: number, input: number): any; - /** Shorthand for ref.writeUInt64LE. */ + /** Shorthand for `ref.writeUInt64LE`. */ writeUInt64LE(offset: number, input: string): any; /** From 660cb0bf913440e5744409a7710a09d51b36b2ce Mon Sep 17 00:00:00 2001 From: Paul Loyd Date: Sun, 8 Sep 2013 14:10:09 +0400 Subject: [PATCH 3/8] Remove repeated info from "ffi" module --- node-ffi/node-ffi.d.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/node-ffi/node-ffi.d.ts b/node-ffi/node-ffi.d.ts index 7c94cc761..9b4987a42 100644 --- a/node-ffi/node-ffi.d.ts +++ b/node-ffi/node-ffi.d.ts @@ -53,20 +53,9 @@ declare module "ffi" { retType: Type; /** The type of arguments. */ argTypes: Type[]; - abi: number; - /** Is set for node-ffi functions. */ ffi_type: NodeBuffer; - /** The size in bytes required to hold this datatype. */ - size: number; - /** The current level of indirection of the buffer. */ - indirection: number; - /** To invoke when `ref.get` is invoked on a buffer of this type. */ - get(buffer: NodeBuffer, offset: number): any; - /** To invoke when `ref.set` is invoked on a buffer of this type. */ - set(buffer: NodeBuffer, offset: number, value): void; - /** The alignment of this datatype when placed inside a struct. */ - alignment: number; + abi: number; /** Get a `Callback` pointer of this function type. */ toPointer(fn: (...args: any[]) => any): NodeBuffer; From 8bbceef0c28a21f91a7d5f36aedd479294b435d8 Mon Sep 17 00:00:00 2001 From: Paul Loyd Date: Tue, 10 Sep 2013 20:30:21 +0400 Subject: [PATCH 4/8] Add "ref-struct" module --- node-ffi/node-ffi-tests.ts | 23 ++++++++++++++ node-ffi/node-ffi.d.ts | 61 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/node-ffi/node-ffi-tests.ts b/node-ffi/node-ffi-tests.ts index a29d8dbd6..06aa2a2ee 100644 --- a/node-ffi/node-ffi-tests.ts +++ b/node-ffi/node-ffi-tests.ts @@ -2,6 +2,7 @@ import ffi = require('ffi'); import ref = require('ref'); +import Struct = require('ref-struct'); { var sqlite3 = ref.types.void; @@ -54,3 +55,25 @@ import ref = require('ref'); var buf = ref.alloc('int64'); ref.writeInt64LE(buf, 0, '9223372036854775807'); } +{ + var S1 = Struct({ a: ref.types.int }); + var S2 = new Struct({ a: 'int' }); +} +{ + var P = new Struct; + P.defineProperty('a', ref.types.int); + P.defineProperty('d', 'long'); +} +{ + var SimpleStruct = Struct({ + first : ref.types.byte, + last : ref.types.byte + }); + + var ss = new SimpleStruct({ first: 50, last: 100 }); + ss.first += 200; +} +{ + var ST = Struct(); + var test: ffi.Type = ST.fields['t'].type; +} diff --git a/node-ffi/node-ffi.d.ts b/node-ffi/node-ffi.d.ts index 9b4987a42..2ec08e813 100644 --- a/node-ffi/node-ffi.d.ts +++ b/node-ffi/node-ffi.d.ts @@ -6,9 +6,7 @@ /// declare module "ffi" { - // import StructType = require('ref-struct'); - - export interface StructType {} + import StructType = require('ref-struct'); export interface Type { /** The size in bytes required to hold this datatype. */ @@ -435,3 +433,60 @@ interface NodeBuffer { */ inspect(): string; } + +declare module "ref-struct" { + import ffi = require('ffi'); + + /** + * This is the `constructor` of the Struct type that gets returned. + * + * Invoke it with `new` to create a new Buffer instance backing the struct. + * Pass it an existing Buffer instance to use that as the backing buffer. + * Pass in an Object containing the struct fields to auto-populate the + * struct with the data. + * + * @constructor + */ + interface StructType extends ffi.Type { + /** Pass it an existing Buffer instance to use that as the backing buffer. */ + new (arg: NodeBuffer, data?: {}): any; + new (data?: {}): any; + /** Pass it an existing Buffer instance to use that as the backing buffer. */ + (arg: NodeBuffer, data?: {}): any; + (data?: {}): any; + + fields: {[key: string]: {type: ffi.Type}}; + + /** + * Adds a new field to the struct instance with the given name and type. + * Note that this function will throw an Error if any instances of the struct + * type have already been created, therefore this function must be called at the + * beginning, before any instances are created. + */ + defineProperty(name: string, type: ffi.Type): void; + + /** + * Adds a new field to the struct instance with the given name and type. + * Note that this function will throw an Error if any instances of the struct + * type have already been created, therefore this function must be called at the + * beginning, before any instances are created. + */ + defineProperty(name: string, type: string): void; + + /** + * Custom for struct type instances. + * @override + */ + toString(): string; + } + + /** The struct type meta-constructor. */ + var StructType: { + new (fields?: {}): StructType; + new (fields?: any[]): StructType; + (fields?: {}): StructType; + (fields?: any[]): StructType; + } + + export = StructType; +} From 450abc694d208f22f9d803bc177902816a7bc5c5 Mon Sep 17 00:00:00 2001 From: Paul Loyd Date: Tue, 10 Sep 2013 20:36:46 +0400 Subject: [PATCH 5/8] Add "ref-union" module --- node-ffi/node-ffi.d.ts | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/node-ffi/node-ffi.d.ts b/node-ffi/node-ffi.d.ts index 2ec08e813..12b8fc326 100644 --- a/node-ffi/node-ffi.d.ts +++ b/node-ffi/node-ffi.d.ts @@ -490,3 +490,61 @@ declare module "ref-struct" { export = StructType; } + +declare module "ref-union" { + import ffi = require('ffi'); + + /** + * This is the `constructor` of the Struct type that gets returned. + * + * Invoke it with `new` to create a new Buffer instance backing the union. + * Pass it an existing Buffer instance to use that as the backing buffer. + * Pass in an Object containing the union fields to auto-populate the + * union with the data. + * + * @constructor + */ + interface UnionType extends ffi.Type { + /** Pass it an existing Buffer instance to use that as the backing buffer. */ + new (arg: NodeBuffer, data?: {}): any; + new (data?: {}): any; + /** Pass it an existing Buffer instance to use that as the backing buffer. */ + (arg: NodeBuffer, data?: {}): any; + (data?: {}): any; + + fields: {[key: string]: {type: ffi.Type}}; + + /** + * Adds a new field to the union instance with the given name and type. + * Note that this function will throw an Error if any instances of the union + * type have already been created, therefore this function must be called at the + * beginning, before any instances are created. + */ + defineProperty(name: string, type: ffi.Type): void; + + /** + * Adds a new field to the union instance with the given name and type. + * Note that this function will throw an Error if any instances of the union + * type have already been created, therefore this function must be called at the + * beginning, before any instances are created. + */ + defineProperty(name: string, type: string): void; + + /** + * Custom for union type instances. + * @override + */ + toString(): string; + } + + /** The union type meta-constructor. */ + var UnionType: { + new (fields?: {}): UnionType; + new (fields?: any[]): UnionType; + (fields?: {}): UnionType; + (fields?: any[]): UnionType; + } + + export = UnionType; +} + From 1bcbd4e538df6907b19bc537da0ebe937a44918d Mon Sep 17 00:00:00 2001 From: Paul Loyd Date: Tue, 10 Sep 2013 21:30:47 +0400 Subject: [PATCH 6/8] Add "ref-array" module --- node-ffi/node-ffi-tests.ts | 26 +++++++++++++++++++++ node-ffi/node-ffi.d.ts | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/node-ffi/node-ffi-tests.ts b/node-ffi/node-ffi-tests.ts index 06aa2a2ee..fae927584 100644 --- a/node-ffi/node-ffi-tests.ts +++ b/node-ffi/node-ffi-tests.ts @@ -3,6 +3,8 @@ import ffi = require('ffi'); import ref = require('ref'); import Struct = require('ref-struct'); +import Union = require('ref-union'); +import TArray = require('ref-array'); { var sqlite3 = ref.types.void; @@ -77,3 +79,27 @@ import Struct = require('ref-struct'); var ST = Struct(); var test: ffi.Type = ST.fields['t'].type; } +{ + var CharArray = TArray('char'); + var b = new Buffer('hello', 'ascii'); + var a = new CharArray(b); +} +{ + var Int32Array = TArray(ref.types.int32); + var input = [1, 4, 91, 123123, 5123512, 0, -1]; + var a = new Int32Array(input); +} +{ + var int = ref.types.int; + var IntArray = TArray(int); + + var buf = new Buffer(int.size * 3); + int.set(buf, int.size * 0, 5); + int.set(buf, int.size * 1, 8); + int.set(buf, int.size * 2, 0); + + var array = IntArray.untilZeros(buf); +} +{ + var refCharArr = TArray('char')([1, 3, 5], 2).ref(); +} diff --git a/node-ffi/node-ffi.d.ts b/node-ffi/node-ffi.d.ts index 12b8fc326..bf8d1327e 100644 --- a/node-ffi/node-ffi.d.ts +++ b/node-ffi/node-ffi.d.ts @@ -434,6 +434,52 @@ interface NodeBuffer { inspect(): string; } +declare module "ref-array" { + import ffi = require('ffi'); + + interface ArrayType extends ffi.Type { + BYTES_PER_ELEMENT: number; + /** The reference to the base type. */ + type: ffi.Type; + + /** + * Accepts a Buffer instance that should be an already-populated with data + * for the ArrayType. The "length" of the Array is determined by searching + * through the buffer's contents until an aligned NULL pointer is encountered. + */ + untilZeros(buffer: NodeBuffer): { [i: number]: number; length: number; + buffer: NodeBuffer; ref(): NodeBuffer; }; + + new (length?: number): { [i: number]: number; length: number; + buffer: NodeBuffer; ref(): NodeBuffer; }; + + new (data: number[], length?: number): { [i: number]: number; length: number; + buffer: NodeBuffer; ref(): NodeBuffer; }; + new (data: NodeBuffer, length?: number): { [i: number]: number; length: number; + buffer: NodeBuffer; ref(): NodeBuffer; }; + (length?: number): { [i: number]: number; length: number; + buffer: NodeBuffer; ref(): NodeBuffer; }; + (data: number[], length?: number): { [i: number]: number; length: number; + buffer: NodeBuffer; ref(): NodeBuffer; }; + (data: NodeBuffer, length?: number): { [i: number]: number; length: number; + buffer: NodeBuffer; ref(): NodeBuffer; }; + } + + /** + * The array type meta-constructor. + * The returned constructor's API is highly influenced by the WebGL + * TypedArray API. + */ + var ArrayType: { + new (type: ffi.Type, length?: number): ArrayType; + new (type: string, length?: number): ArrayType; + (type: ffi.Type, length?: number): ArrayType; + (type: string, length?: number): ArrayType; + }; + + export = ArrayType; +} + declare module "ref-struct" { import ffi = require('ffi'); From 545340a97016ce36db871f73099d989430f99c25 Mon Sep 17 00:00:00 2001 From: Paul Loyd Date: Tue, 10 Sep 2013 21:36:06 +0400 Subject: [PATCH 7/8] Move Type interface from "ffi" module into "ref" module --- node-ffi/node-ffi-tests.ts | 2 +- node-ffi/node-ffi.d.ts | 133 ++++++++++++++++++------------------- 2 files changed, 67 insertions(+), 68 deletions(-) diff --git a/node-ffi/node-ffi-tests.ts b/node-ffi/node-ffi-tests.ts index fae927584..c646af703 100644 --- a/node-ffi/node-ffi-tests.ts +++ b/node-ffi/node-ffi-tests.ts @@ -77,7 +77,7 @@ import TArray = require('ref-array'); } { var ST = Struct(); - var test: ffi.Type = ST.fields['t'].type; + var test: ref.Type = ST.fields['t'].type; } { var CharArray = TArray('char'); diff --git a/node-ffi/node-ffi.d.ts b/node-ffi/node-ffi.d.ts index bf8d1327e..301331edc 100644 --- a/node-ffi/node-ffi.d.ts +++ b/node-ffi/node-ffi.d.ts @@ -6,23 +6,9 @@ /// declare module "ffi" { + import ref = require('ref'); import StructType = require('ref-struct'); - export interface Type { - /** The size in bytes required to hold this datatype. */ - size: number; - /** The current level of indirection of the buffer. */ - indirection: number; - /** To invoke when `ref.get` is invoked on a buffer of this type. */ - get(buffer: NodeBuffer, offset: number): any; - /** To invoke when `ref.set` is invoked on a buffer of this type. */ - set(buffer: NodeBuffer, offset: number, value): void; - /** The name to use during debugging for this datatype. */ - name?: string; - /** The alignment of this datatype when placed inside a struct. */ - alignment?: number; - } - /** Provides a friendly API on-top of `DynamicLibrary` and `ForeignFunction`. */ export var Library: { /** The extension to use on libraries. */ @@ -46,11 +32,11 @@ declare module "ffi" { /** Get value of errno. */ export function errno(): number; - export interface Function extends Type { + export interface Function extends ref.Type { /** The type of return value. */ - retType: Type; + retType: ref.Type; /** The type of arguments. */ - argTypes: Type[]; + argTypes: ref.Type[]; /** Is set for node-ffi functions. */ ffi_type: NodeBuffer; abi: number; @@ -63,9 +49,9 @@ declare module "ffi" { /** Creates and returns a type for a C function pointer. */ export var Function: { - new (retType: Type, argTypes: any[], abi?: number): Function; + new (retType: ref.Type, argTypes: any[], abi?: number): Function; new (retType: string, argTypes: any[], abi?: number): Function; - (retType: Type, argTypes: any[], abi?: number): Function; + (retType: ref.Type, argTypes: any[], abi?: number): Function; (retType: string, argTypes: any[], abi?: number): Function; }; @@ -81,9 +67,9 @@ declare module "ffi" { * execution. */ export var ForeignFunction: { - new (ptr: NodeBuffer, retType: Type, argTypes: any[], abi?: number): ForeignFunction; + new (ptr: NodeBuffer, retType: ref.Type, argTypes: any[], abi?: number): ForeignFunction; new (ptr: NodeBuffer, retType: string, argTypes: any[], abi?: number): ForeignFunction; - (ptr: NodeBuffer, retType: Type, argTypes: any[], abi?: number): ForeignFunction; + (ptr: NodeBuffer, retType: ref.Type, argTypes: any[], abi?: number): ForeignFunction; (ptr: NodeBuffer, retType: string, argTypes: any[], abi?: number): ForeignFunction; } @@ -110,9 +96,9 @@ declare module "ffi" { * contain the same ffi_type argument signature. */ export var VariadicForeignFunction: { - new (ptr: NodeBuffer, ret: Type, fixedArgs: any[], abi?: number): VariadicForeignFunction; + new (ptr: NodeBuffer, ret: ref.Type, fixedArgs: any[], abi?: number): VariadicForeignFunction; new (ptr: NodeBuffer, ret: string, fixedArgs: any[], abi?: number): VariadicForeignFunction; - (ptr: NodeBuffer, ret: Type, fixedArgs: any[], abi?: number): VariadicForeignFunction; + (ptr: NodeBuffer, ret: ref.Type, fixedArgs: any[], abi?: number): VariadicForeignFunction; (ptr: NodeBuffer, ret: string, fixedArgs: any[], abi?: number): VariadicForeignFunction; }; @@ -162,7 +148,7 @@ declare module "ffi" { export var ffiType: { /** Get a `ffi_type *` Buffer appropriate for the given type. */ - (type: Type): NodeBuffer + (type: ref.Type): NodeBuffer /** Get a `ffi_type *` Buffer appropriate for the given type. */ (type: string): NodeBuffer FFI_TYPE: StructType; @@ -193,20 +179,33 @@ declare module "ffi" { /** Default types. */ export var types: { - void: Type; int64: Type; ushort: Type; - int: Type; uint64: Type; float: Type; - uint: Type; long: Type; double: Type; - int8: Type; ulong: Type; Object: Type; - uint8: Type; longlong: Type; CString: Type; - int16: Type; ulonglong: Type; bool: Type; - uint16: Type; char: Type; byte: Type; - int32: Type; uchar: Type; size_t: Type; - uint32: Type; short: Type; + void: ref.Type; int64: ref.Type; ushort: ref.Type; + int: ref.Type; uint64: ref.Type; float: ref.Type; + uint: ref.Type; long: ref.Type; double: ref.Type; + int8: ref.Type; ulong: ref.Type; Object: ref.Type; + uint8: ref.Type; longlong: ref.Type; CString: ref.Type; + int16: ref.Type; ulonglong: ref.Type; bool: ref.Type; + uint16: ref.Type; char: ref.Type; byte: ref.Type; + int32: ref.Type; uchar: ref.Type; size_t: ref.Type; + uint32: ref.Type; short: ref.Type; }; } declare module "ref" { - import ffi = require('ffi'); + export interface Type { + /** The size in bytes required to hold this datatype. */ + size: number; + /** The current level of indirection of the buffer. */ + indirection: number; + /** To invoke when `ref.get` is invoked on a buffer of this type. */ + get(buffer: NodeBuffer, offset: number): any; + /** To invoke when `ref.set` is invoked on a buffer of this type. */ + set(buffer: NodeBuffer, offset: number, value): void; + /** The name to use during debugging for this datatype. */ + name?: string; + /** The alignment of this datatype when placed inside a struct. */ + alignment?: number; + } /** A Buffer that references the C NULL pointer. */ export var NULL: NodeBuffer; @@ -215,7 +214,7 @@ declare module "ref" { /** Get the memory address of buffer. */ export function address(buffer: NodeBuffer): number; /** Allocate the memory with the given value written to it. */ - export function alloc(type: ffi.Type, value?): NodeBuffer; + export function alloc(type: Type, value?): NodeBuffer; /** Allocate the memory with the given value written to it. */ export function alloc(type: string, value?): NodeBuffer; @@ -227,9 +226,9 @@ declare module "ref" { export function allocCString(string: string, encoding?: string): NodeBuffer; /** Coerce a type.*/ - export function coerceType(type: ffi.Type): ffi.Type; + export function coerceType(type: Type): Type; /** Coerce a type. String are looked up from the ref.types object. */ - export function coerceType(type: string): ffi.Type; + export function coerceType(type: string): Type; /** * Get value after dereferencing buffer. @@ -240,17 +239,17 @@ declare module "ref" { export function deref(buffer: NodeBuffer): any; /** Create clone of the type, with decremented indirection level by 1. */ - export function derefType(type: ffi.Type): ffi.Type; + export function derefType(type: Type): Type; /** Create clone of the type, with decremented indirection level by 1. */ - export function derefType(type: string): ffi.Type; + export function derefType(type: string): Type; /** Represents the native endianness of the processor ("LE" or "BE"). */ export var endianness: string; /** Check the indirection level and return a dereferenced when necessary. */ - export function get(buffer: NodeBuffer, offset?: number, type?: ffi.Type): any; + export function get(buffer: NodeBuffer, offset?: number, type?: Type): any; /** Check the indirection level and return a dereferenced when necessary. */ export function get(buffer: NodeBuffer, offset?: number, type?: string): any; /** Get type of the buffer. Create a default type when none exists. */ - export function getType(buffer: NodeBuffer): ffi.Type; + export function getType(buffer: NodeBuffer): Type; /** Check the NULL. */ export function isNull(buffer: NodeBuffer): boolean; /** Read C string until the first NULL. */ @@ -292,9 +291,9 @@ declare module "ref" { /** Create pointer to buffer. */ export function ref(buffer: NodeBuffer): NodeBuffer; /** Create clone of the type, with incremented indirection level by 1. */ - export function refType(type: ffi.Type): ffi.Type; + export function refType(type: Type): Type; /** Create clone of the type, with incremented indirection level by 1. */ - export function refType(type: string): ffi.Type; + export function refType(type: string): Type; /** * Create buffer with the specified size, with the same address as source. @@ -311,7 +310,7 @@ declare module "ref" { offset?: number): NodeBuffer; /** Write pointer if the indirection is 1, otherwise write value. */ - export function set(buffer: NodeBuffer, offset: number, value, type?: ffi.Type): void; + export function set(buffer: NodeBuffer, offset: number, value, type?: Type): void; /** Write pointer if the indirection is 1, otherwise write value. */ export function set(buffer: NodeBuffer, offset: number, value, type?: string): void; /** Write the string as a NULL terminated. Default encoding is utf8. */ @@ -364,15 +363,15 @@ declare module "ref" { /** Default types. */ export var types: { - void: ffi.Type; int64: ffi.Type; ushort: ffi.Type; - int: ffi.Type; uint64: ffi.Type; float: ffi.Type; - uint: ffi.Type; long: ffi.Type; double: ffi.Type; - int8: ffi.Type; ulong: ffi.Type; Object: ffi.Type; - uint8: ffi.Type; longlong: ffi.Type; CString: ffi.Type; - int16: ffi.Type; ulonglong: ffi.Type; bool: ffi.Type; - uint16: ffi.Type; char: ffi.Type; byte: ffi.Type; - int32: ffi.Type; uchar: ffi.Type; size_t: ffi.Type; - uint32: ffi.Type; short: ffi.Type; + void: Type; int64: Type; ushort: Type; + int: Type; uint64: Type; float: Type; + uint: Type; long: Type; double: Type; + int8: Type; ulong: Type; Object: Type; + uint8: Type; longlong: Type; CString: Type; + int16: Type; ulonglong: Type; bool: Type; + uint16: Type; char: Type; byte: Type; + int32: Type; uchar: Type; size_t: Type; + uint32: Type; short: Type; }; } @@ -435,12 +434,12 @@ interface NodeBuffer { } declare module "ref-array" { - import ffi = require('ffi'); + import ref = require('ref'); - interface ArrayType extends ffi.Type { + interface ArrayType extends ref.Type { BYTES_PER_ELEMENT: number; /** The reference to the base type. */ - type: ffi.Type; + type: ref.Type; /** * Accepts a Buffer instance that should be an already-populated with data @@ -471,9 +470,9 @@ declare module "ref-array" { * TypedArray API. */ var ArrayType: { - new (type: ffi.Type, length?: number): ArrayType; + new (type: ref.Type, length?: number): ArrayType; new (type: string, length?: number): ArrayType; - (type: ffi.Type, length?: number): ArrayType; + (type: ref.Type, length?: number): ArrayType; (type: string, length?: number): ArrayType; }; @@ -481,7 +480,7 @@ declare module "ref-array" { } declare module "ref-struct" { - import ffi = require('ffi'); + import ref = require('ref'); /** * This is the `constructor` of the Struct type that gets returned. @@ -493,7 +492,7 @@ declare module "ref-struct" { * * @constructor */ - interface StructType extends ffi.Type { + interface StructType extends ref.Type { /** Pass it an existing Buffer instance to use that as the backing buffer. */ new (arg: NodeBuffer, data?: {}): any; new (data?: {}): any; @@ -501,7 +500,7 @@ declare module "ref-struct" { (arg: NodeBuffer, data?: {}): any; (data?: {}): any; - fields: {[key: string]: {type: ffi.Type}}; + fields: {[key: string]: {type: ref.Type}}; /** * Adds a new field to the struct instance with the given name and type. @@ -509,7 +508,7 @@ declare module "ref-struct" { * type have already been created, therefore this function must be called at the * beginning, before any instances are created. */ - defineProperty(name: string, type: ffi.Type): void; + defineProperty(name: string, type: ref.Type): void; /** * Adds a new field to the struct instance with the given name and type. @@ -538,7 +537,7 @@ declare module "ref-struct" { } declare module "ref-union" { - import ffi = require('ffi'); + import ref = require('ref'); /** * This is the `constructor` of the Struct type that gets returned. @@ -550,7 +549,7 @@ declare module "ref-union" { * * @constructor */ - interface UnionType extends ffi.Type { + interface UnionType extends ref.Type { /** Pass it an existing Buffer instance to use that as the backing buffer. */ new (arg: NodeBuffer, data?: {}): any; new (data?: {}): any; @@ -558,7 +557,7 @@ declare module "ref-union" { (arg: NodeBuffer, data?: {}): any; (data?: {}): any; - fields: {[key: string]: {type: ffi.Type}}; + fields: {[key: string]: {type: ref.Type}}; /** * Adds a new field to the union instance with the given name and type. @@ -566,7 +565,7 @@ declare module "ref-union" { * type have already been created, therefore this function must be called at the * beginning, before any instances are created. */ - defineProperty(name: string, type: ffi.Type): void; + defineProperty(name: string, type: ref.Type): void; /** * Adds a new field to the union instance with the given name and type. From 1f5739a2e234f3179612c2a2137c9241673771c6 Mon Sep 17 00:00:00 2001 From: Paul Loyd Date: Tue, 10 Sep 2013 21:52:31 +0400 Subject: [PATCH 8/8] Add info to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7e0d99ffb..b71264e6c 100755 --- a/README.md +++ b/README.md @@ -153,6 +153,7 @@ List of Definitions * [Mustache.js](https://github.com/janl/mustache.js) (by [Boris Yankov](https://github.com/borisyankov)) * [Node.js](http://nodejs.org/) (from TypeScript samples) * [node_redis](https://github.com/mranney/node_redis) (by [Boris Yankov](https://github.com/borisyankov)) +* [node-ffi](https://github.com/rbranson/node-ffi) (by [Paul Loyd](https://github.com/loyd)) * [node_zeromq](https://github.com/JustinTulloss/zeromq.node) (by [Dave McKeown](https://github.com/davemckeown)) * [node-sqlserver](https://github.com/WindowsAzure/node-sqlserver) (by [Boris Yankov](https://github.com/borisyankov)) * [Numeral.js](https://github.com/adamwdraper/Numeral-js) (by [Vincent Bortone](https://github.com/vbortone/))