* 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.
(funcPtr, returnType, fixedArgTypes, abi)
| 22 | */ |
| 23 | |
| 24 | function VariadicForeignFunction (funcPtr, returnType, fixedArgTypes, abi) { |
| 25 | debug('creating new VariadicForeignFunction', funcPtr) |
| 26 | |
| 27 | // the cache of ForeignFunction instances that this |
| 28 | // VariadicForeignFunction has created so far |
| 29 | var cache = {} |
| 30 | |
| 31 | // check args |
| 32 | assert(Buffer.isBuffer(funcPtr), 'expected Buffer as first argument') |
| 33 | assert(!!returnType, 'expected a return "type" object as the second argument') |
| 34 | assert(Array.isArray(fixedArgTypes), 'expected Array of arg "type" objects as the third argument') |
| 35 | |
| 36 | var numFixedArgs = fixedArgTypes.length |
| 37 | |
| 38 | // normalize the "types" (they could be strings, |
| 39 | // so turn into real type instances) |
| 40 | fixedArgTypes = fixedArgTypes.map(ref.coerceType) |
| 41 | |
| 42 | // get the names of the fixed arg types |
| 43 | var fixedKey = fixedArgTypes.map(function (type) { |
| 44 | return getId(type) |
| 45 | }) |
| 46 | |
| 47 | |
| 48 | // what gets returned is another function that needs to be invoked with the rest |
| 49 | // of the variadic types that are being invoked from the function. |
| 50 | function variadic_function_generator () { |
| 51 | debug('variadic_function_generator invoked') |
| 52 | |
| 53 | // first get the types of variadic args we are working with |
| 54 | var argTypes = fixedArgTypes.slice() |
| 55 | var key = fixedKey.slice() |
| 56 | |
| 57 | for (var i = 0; i < arguments.length; i++) { |
| 58 | var type = ref.coerceType(arguments[i]) |
| 59 | argTypes.push(type) |
| 60 | |
| 61 | var ffi_type = Type(type) |
| 62 | assert(ffi_type.name) |
| 63 | key.push(getId(type)) |
| 64 | } |
| 65 | |
| 66 | // now figure out the return type |
| 67 | var rtnType = ref.coerceType(variadic_function_generator.returnType) |
| 68 | var rtnName = getId(rtnType) |
| 69 | assert(rtnName) |
| 70 | |
| 71 | // first let's generate the key and see if we got a cache-hit |
| 72 | key = rtnName + key.join('') |
| 73 | |
| 74 | var func = cache[key] |
| 75 | if (func) { |
| 76 | debug('cache hit for key:', key) |
| 77 | } else { |
| 78 | // create the `ffi_cif *` instance |
| 79 | debug('creating the variadic ffi_cif instance for key:', key) |
| 80 | var cif = CIF_var(returnType, argTypes, numFixedArgs, abi) |
| 81 | func = cache[key] = _ForeignFunction(cif, funcPtr, rtnType, argTypes) |