Skip to content

API changes from v0.x to v1.x

TooTallNate edited this page May 12, 2012 · 18 revisions

Most of the API's in node-ffi changed in v1.x to be more concise.

The "Pointer" class is GONE!

The main change is that the old Pointer class has been completely removed, in favor of using official Node Buffer objects everywhere. The Pointer class had some additional functionality over vanilla Buffers, so ref was written to iron out those differences.

So anywhere where you have ffi.Pointer in your code, that will need to be changed to use vanilla Buffers. Read up on these subjects if you are not familiar with them:

The "type" system

ref introduces a "type" system, which allows you to classify the data inside a Buffer as an int, or char *, etc. So now node-ffi uses these "type" objects when defining FFI functions:

var ref = require('ref')
var ffi = require('node-ffi')

// the "int" type
var int = ref.types.int

// create an FFI'd "abs(3)" function
var absPtr = ffi.DynamicLibrary().get('abs')
var abs = ffi.ForeignFunction(absPtr, int, [ int ])

// and invoke!
abs(-1)   // ← 1
abs(-123) // ← 123

String-name specifiers

ref supports String shorthands for these types. So "int" gets coerced into ref.types.int. This is mostly for convenience and backwards compatibility with old node-ffi apps/modules.

The "pointer" type

The old "pointer" type should not be used anymore! This is because "pointer" is ambiguous, and node-ffi has no idea what the pointer represents. Instead, pass in an explicit "reference" type.

So if you had a function that accepts an int * type, then you can create an appropriate "type" for that by invoking:

var intPtr = ref.refType(ref.types.int)

// and now you can pass in the "int *" type to ForeignFunction, Library, or Callback
var func = ffi.ForeignFunction(funcPtr, 'void', [ intPtr ])

The "string" type

The old "string" type specifier stil works, but is discouraged from being used. The "preferred" way to specify string arg or return types is with a proper char * type, like so:

vart charPtr = ref.refType(ref.types.char)

// create an FFI'd function that takes 0 arguments and returns a `char *` that is a C String
var func = ffi.ForeignFunction(funcPtr, charPtr, [])

// then you can read the C String from the returned Buffer when invoked
var rtn = func()
rtn.readCString()

// this is important for C functions that require you to free() the string manually
free(rtn)

Async FFI'd Functions

The API for invoking asynchronous ForeignFunction instances has changed. Previously, you'd have to specify whether a ForeignFunction instance was "async" during instantiation, but now you can decide at call-time. The "regular" function invokation (i.e. func()) is the "sync" version, and calling func.async() with a callback function is the "async" version.

Additionally, before an async invokation would return an EventEmitter instance that would emit "success" when the FFI'd function completed. This was unnecessary, and now you simply pass the .async() function a callback function as the final argument. The callback follows Node's the traditional err, res argument signature.

Before:

var func = new ffi.ForeignFunction(funcPtr, 'int', [ 'int' ], true)
func(-5).on('success', function (res) {
  console.log('result:', res)
})

Now:

var func = ffi.ForeignFunction(funcPtr, 'int', [ 'int' ]) // no need to specify "async" here...
func(-5)  // "sync" version
func.async(-5, function (err, res) {  // "async" version
  if (err) throw err
  console.log('result:', res)
})

More coming soon!

Clone this wiki locally