Squeak
  links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
How to Use FFI
Last updated at 6:59 pm UTC on 17 September 2019
Squeak allows calling functions in the underlying platform's libraries. These 'ffi' (Foreign Function Interface) calls are analogous to Primitive Methods, but they can call arbitrary functions.

Installation

The FFI package is available via several tools.

The SqueakMap catalog provides access to the latest version as well as several older Squeak specific version. Simply select the one you need and click the Install button as usual.
The package is also available via Metacello - just 'do it' on
 Metacello new
	configuration: 'FFI';
	load.

Installation Squeak 5.3

Through the PreferenceWizardMorph

FFI_checkbox_in_PreferenceWizard.png
This uses the Metacello method shown above.

Installation (Squeak 5.0 and later)

(Installer repository: 'http://source.squeak.org/FFI')
    install: 'FFI-Pools';
    install: 'FFI-Kernel';
    install: 'FFI-Tests';
    install: 'FFI-Examples'.
or, if you don't want the examples & tests
(Installer repository: 'http://source.squeak.org/FFI')
   install: 'FFI-Pools';
    install: 'FFI-Kernel'.

Methods invoking external functions

To call an external function, we need to make a method that includes a suitable pragma that specifies the function to use, the library that provides it and the type signature(s) of the function and parameters. This looks very similar to a named primitive method in the simplest cases
For example
testAbs: anInteger
"Simple example of an ffi call to the stdlib"
"This version uses the name for the linux club; different systems use different names just to be a pain"
	<cdecl: long 'abs' (long) module:  'libc.so.6' >
	^self externalCallFailed


The first line should be the external function specification pragma. Following the external function specification is normal Smalltalk code that is executed if the external function call fails.
It's important to remember that failure here means something went wrong in linking to and calling the external function, not that the function could not do its internal job. Thus, the most common code is simply '^self externalCallFailed.'

The pragma is always of the form
 < calltype: returntype 'function name' (list of parameter types) module: 'library name' > 


Parameter Types

Argument and return types must be names of ExternalTypes. These can be one of the atomic types (see ExternalType class>>initializeFFIConstants and ExternalType class>>initializeAtomicTypes):

ExternalTypes can also be structure types, referred to by the name of a subclass of ExternalStructure with '*' appended to indicate that the argument or return is a pointer to that structure. See the next section.

Structure Types

If the function you want to call has a return or argument type that is a structure type that is not already present as a subclass of ExternalStructure, you'll need to create one. The most important bit is to write a class-side method 'fields' that returns an array of field descriptions. Each field description is a 2 or 3 element array, the first element of which is the field name and the second is the type. The optional third element is a number of extra bytes to be added in the structure, presumably and some form of alignment correction? Then send the class #defineFields to initialize it with your new implementation of #fields. Be sure to have for each subclass of ExternalStructure a class-side #initialize method that includes "self defineFields" or the class won't work after being loaded into another image.

For example, a pixel color structure might implemented so:

maybe, like this:

fields 

^#((red   'byte')
   (green 'byte')
   (blue  'byte'))                




Comments