Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
numElements += 1;
}
}
// hand-crafting a null-terminated array here.
// XXX: use "ref-array"?
const size = ref.sizeof.pointer * (numElements + 1); // +1 because of the NULL terminator
const elements = ffi_type.elements = Buffer.alloc(size);
let index = 0;
for (let i = 0; i < numFields; i++) {
field = fields[fieldNames[i]];
if (field.type.fixedLength > 0) {
// a fixed-length "ref-array" type
ffi_type_ptr = Type(field.type.type);
for (var j = 0; j < field.type.fixedLength; j++) {
elements.writePointer(ffi_type_ptr, (index++) * ref.sizeof.pointer);
}
} else {
ffi_type_ptr = Type(field.type);
elements.writePointer(ffi_type_ptr, (index++) * ref.sizeof.pointer);
}
}
// final NULL pointer to terminate the Array
elements.writePointer(ref.NULL, index * ref.sizeof.pointer);
// also set the `ffi_type` property to that it's cached for next time
ret = type.ffi_type = ffi_type.ref();
}
if (!ret && type.name) {
// handle "ref" types other than the set that node-ffi is using (i.e.
// a separate copy)
if ('CString' == type.name) {
'use strict';
/**
* Module dependencies.
*/
var Type = require('./type');
const assert = require('assert');
const debug = require('debug')('ffi:cif');
const ref = require('ref-napi');
const bindings = require('./bindings');
const POINTER_SIZE = ref.sizeof.pointer;
const ffi_prep_cif = bindings.ffi_prep_cif;
const FFI_CIF_SIZE = bindings.FFI_CIF_SIZE;
const FFI_DEFAULT_ABI = bindings.FFI_DEFAULT_ABI;
// status codes
const FFI_OK = bindings.FFI_OK;
const FFI_BAD_TYPEDEF = bindings.FFI_BAD_TYPEDEF;
const FFI_BAD_ABI = bindings.FFI_BAD_ABI;
/**
* JS wrapper for the `ffi_prep_cif` function.
* Returns a Buffer instance representing a `ffi_cif *` instance.
*/
const cifs = [];
function CIF (rtype, types, abi) {
debug('creating `ffi_cif *` instance');
});
// make `size_t` use the "ffi_type_pointer"
ref.types.size_t.ffi_type = bindings.FFI_TYPES.pointer;
// make `Utf8String` use "ffi_type_pointer"
const CString = ref.types.CString || ref.types.Utf8String;
CString.ffi_type = bindings.FFI_TYPES.pointer;
// make `Object` use the "ffi_type_pointer"
ref.types.Object.ffi_type = bindings.FFI_TYPES.pointer;
// libffi is weird when it comes to long data types (defaults to 64-bit),
// so we emulate here, since some platforms have 32-bit longs and some
// platforms have 64-bit longs.
switch (ref.sizeof.long) {
case 4:
ref.types.ulong.ffi_type = bindings.FFI_TYPES.uint32;
ref.types.long.ffi_type = bindings.FFI_TYPES.int32;
break;
case 8:
ref.types.ulong.ffi_type = bindings.FFI_TYPES.uint64;
ref.types.long.ffi_type = bindings.FFI_TYPES.int64;
break;
default:
throw new Error('unsupported "long" size: ' + ref.sizeof.long);
}
/**
* Alias the "ref" types onto ffi's exports, for convenience...
*/
function ForeignFunction (cif, funcPtr, returnType, argTypes) {
debug('creating new ForeignFunction', funcPtr);
const numArgs = argTypes.length;
const argsArraySize = numArgs * POINTER_SIZE;
// "result" must point to storage that is sizeof(long) or larger. For smaller
// return value sizes, the ffi_arg or ffi_sarg integral type must be used to
// hold the return value
const resultSize = returnType.size >= ref.sizeof.long ? returnType.size : FFI_ARG_SIZE;
assert(resultSize > 0);
/**
* This is the actual JS function that gets returned.
* It handles marshalling input arguments into C values,
* and unmarshalling the return value back into a JS value
*/
const proxy = function () {
debug('invoking proxy function');
if (arguments.length !== numArgs) {
throw new TypeError('Expected ' + numArgs +
' arguments, got ' + arguments.length);
}
'use strict';
/**
* Module dependencies.
*/
const assert = require('assert');
const debug = require('debug')('ffi:_ForeignFunction');
const ref = require('ref-napi');
const bindings = require('./bindings');
const POINTER_SIZE = ref.sizeof.pointer;
const FFI_ARG_SIZE = bindings.FFI_ARG_SIZE;
function ForeignFunction (cif, funcPtr, returnType, argTypes) {
debug('creating new ForeignFunction', funcPtr);
const numArgs = argTypes.length;
const argsArraySize = numArgs * POINTER_SIZE;
// "result" must point to storage that is sizeof(long) or larger. For smaller
// return value sizes, the ffi_arg or ffi_sarg integral type must be used to
// hold the return value
const resultSize = returnType.size >= ref.sizeof.long ? returnType.size : FFI_ARG_SIZE;
assert(resultSize > 0);
/**
'use strict';
/**
* Module dependencies.
*/
const CIF_var = require('./cif_var');
const Type = require('./type');
const _ForeignFunction = require('./_foreign_function');
const assert = require('assert');
const debug = require('debug')('ffi:VariadicForeignFunction');
const ref = require('ref-napi');
const bindings = require('./bindings');
const POINTER_SIZE = ref.sizeof.pointer;
const FFI_ARG_SIZE = bindings.FFI_ARG_SIZE;
/**
* 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.
*/
function VariadicForeignFunction (funcPtr, returnType, fixedArgTypes, abi) {
debug('creating new VariadicForeignFunction', funcPtr);
// the cache of ForeignFunction instances that this
// VariadicForeignFunction has created so far
const cache = {};
'use strict';
/**
* Module dependencies.
*/
const Type = require('./type');
const assert = require('assert');
const debug = require('debug')('ffi:cif_var');
const ref = require('ref-napi');
const bindings = require('./bindings');
const POINTER_SIZE = ref.sizeof.pointer;
const ffi_prep_cif_var = bindings.ffi_prep_cif_var;
const FFI_CIF_SIZE = bindings.FFI_CIF_SIZE;
const FFI_DEFAULT_ABI = bindings.FFI_DEFAULT_ABI;
// status codes
const FFI_OK = bindings.FFI_OK;
const FFI_BAD_TYPEDEF = bindings.FFI_BAD_TYPEDEF;
const FFI_BAD_ABI = bindings.FFI_BAD_ABI;
/**
* JS wrapper for the `ffi_prep_cif_var` function.
* Returns a Buffer instance representing a variadic `ffi_cif *` instance.
*/
function CIF_var (rtype, types, numFixedArgs, abi) {
debug('creating `ffi_cif *` instance with `ffi_prep_cif_var()`');
ref.types.Object.ffi_type = bindings.FFI_TYPES.pointer;
// libffi is weird when it comes to long data types (defaults to 64-bit),
// so we emulate here, since some platforms have 32-bit longs and some
// platforms have 64-bit longs.
switch (ref.sizeof.long) {
case 4:
ref.types.ulong.ffi_type = bindings.FFI_TYPES.uint32;
ref.types.long.ffi_type = bindings.FFI_TYPES.int32;
break;
case 8:
ref.types.ulong.ffi_type = bindings.FFI_TYPES.uint64;
ref.types.long.ffi_type = bindings.FFI_TYPES.int64;
break;
default:
throw new Error('unsupported "long" size: ' + ref.sizeof.long);
}
/**
* Alias the "ref" types onto ffi's exports, for convenience...
*/
exports.types = ref.types;
// Include our other modules
exports.version = bindings.version;
exports.CIF = require('./cif');
exports.CIF_var = require('./cif_var');
exports.Function = require('./function');
exports.ForeignFunction = require('./foreign_function');
exports.VariadicForeignFunction = require('./foreign_function_var');
exports.DynamicLibrary = require('./dynamic_library');
const callback = _Callback(cif, retType.size, argc, errorReportCallback, (retval, params) => {
debug('Callback function being invoked')
try {
const args = [];
for (var i = 0; i < argc; i++) {
const type = argTypes[i];
const argPtr = params.readPointer(i * ref.sizeof.pointer, type.size);
argPtr.type = type;
args.push(argPtr.deref());
}
// Invoke the user-given function
const result = func.apply(null, args);
try {
ref.set(retval, 0, result, retType);
} catch (e) {
e.message = 'error setting return value - ' + e.message;
throw e;
}
} catch (e) {
return e;
}
});
this.retType = ref.coerceType(retType);
this.argTypes = argTypes.map(ref.coerceType);
this.abi = null == abi ? bindings.FFI_DEFAULT_ABI : abi;
}
/**
* The "ffi_type" is set for node-ffi functions.
*/
Function.prototype.ffi_type = bindings.FFI_TYPES.pointer;
/**
* The "size" is always pointer-sized.
*/
Function.prototype.size = ref.sizeof.pointer;
/**
* The "alignment" is always pointer-aligned.
*/
Function.prototype.alignment = ref.alignof.pointer;
/**
* The "indirection" is always 1 to ensure that our get()/set() get called.
*/
Function.prototype.indirection = 1;
/**
* Returns a ffi.Callback pointer (Buffer) of this function type for the
* given `fn` Function.