[Pharo-project] FFI Documentation
stephane.ducasse at inria.fr
Thu May 20 21:25:59 CEST 2010
this is cool to see such kind of documentation emerging.
On May 20, 2010, at 9:16 PM, Sean P. DeNigris wrote:
> I want to get this info into the help system and/or collaborative book, as
> similar questions pop up regularly on the lists.
> I compiled every piece of info I could find. The focus in on FFI, with
> stubs for other strategies. Please read this *very* rough outline for
> missing info and inaccuracies:
> What is FFI and what is it used for? Calling functions in libraries outside
> of the image...
> FFI, the Squeak Foreign Function Interface, is used to call functions
> located in shared libraries that are not part of the Squeak VM nor its
> plugins. It also provides means to read and write memory structures that are
> associated with the use of those shared libraries. A typical use is to
> directly invoke operating system APIs. As such, applications that use FFI
> can only be used on the platform(s) that support the particular API being
> used. C conventions are used throughout, though the external function could
> have been written by any language capable of generating object code that
> follows C conventions. FFI is probably the easiest way to do the things it
> does. FFI is pretty fast too. Croquet uses FFI calls to OpenGL for all it's
> drawing routines.
> How does FFI work?
> Technically what happens is:
> * you define what the interface is - the parameters, types etc.
> * when you make the call, the FFI logic assembles the data from the Squeak
> Objects into the proper structures according to the routine calling
> conventions for your architecture, and of course manages the return values.
> So no magic but perhaps just a little assembler in the plugin to properly
> deal with all the registers and condition flags.
> How do I use it?
> 1. make a method (whose structure is similar to a named primitive method)
> system: aString "name (by convention is apiXxx: e.g. apiSystem:)"
> <apicall: long 'system' (char*) module: 'libSystem.dylib'> "first line
> should be the external function specification"
> ^self externalCallFailed.
> Let's take it piece by piece:
> system: aString
> Method name - by convention named 'apiXxx'
> <apicall: long 'system' (char*) module: 'libSystem.dylib'>
> Function specification
> - should be the first line
> - enclosed in angle brackets: < > containing:
> 1. Calling Convention, either apicall: (Pascal convention) or cdecl: (C
> - Mac - use either one
> - Unix - use cdecl
> - Windows - use apical
> 2. Return Type (see types)
> 3. External Function Name (literal string)
> 4. Argument Types (a literal array)
> 5. Module - "module: " + [filename of the external library (literal
> string)] (see below).
> self externalCallFailed.
> Failure handler
> - normal smalltalk code
> - executed if the linking to or calling the external function fails
> - API calls don't know how to communicate failure like Squeak primitives
> do, so:
> - it does not tell you whether the external function succeeded
> - the most common code is simply '^self externalCallFailed.'
> Argument Types
> - must be names of ExternalTypes, either:
> - atomic types (see ExternalType class>>initializeFFIConstants and
> ExternalType class>>initializeAtomicTypes):
> byte (unsigned)
> sbyte (signed)
> ushort (16-bit unsigned)
> short (16-bit signed)
> ulong (32-bit unsigned)
> long (32-bit signed)
> ulonglong (64-bit unsigned)
> longlong (64-bit signed)
> char (unsigned)
> schar (signed)
> float (single-precision float)
> double (double-precision float)
> Structure Types 
> - subclass of ExternalStructure
> - class>>fields that returns an array of field descriptions (see below)
> - Example:
> ^#((red 'byte')(green 'byte')(blue 'byte'))
> - class>>initialize which includes "self defineFields" (which must be
> called before using the class)
> - refer to as MyExternalStructure* (to indicate that the argument or return
> is a pointer to that structure)
> Field description 
> - 2-element array (or three but that does something else, I'm not sure
> - first element is the field name
> - second is the type
> Mac Memory Allocation Issues  (not sure about this)
> If you allocate external structures, those with memory outside the Squeak
> process space, you may need to increase the amount of memory that is
> reserved outside the object heap for such use. The Mac OS (9 and previous)
> needs this, other platforms may be able to dynamically get more memory from
> the OS. To see how much memory is currently reserved printIt 'Smalltalk
> extraVMMemory'. To change it, execute 'Smalltalk extraVMMemory:
> someNumberofBytes' Then save your image and quit. When you next start up,
> the amount of memory you requested will be reserved. (JMM) Note the OSX
> versions of the VM ignore extraVMMemory because the memory model for
> OS-X/unix applications is quite different.
> Module Name
> - depends on the platform
> - Mac
> - pre Snow Leopard: flexible, can eliminate leading lib or extension e.g.
> 'libc.dylib' becomes 'libc', 'c.dylib', or 'c'
> - Snow Leopard
> - file name must be exact including extension (unless Info.plist is
> altered as in 'Library Location' below)
> - With pre-mach-o VMs
> - For Classic applications, use 'InterfaceLib'
> - For Carbon libs, use 'CarbonLib'
> Module Location - where the external library file lives
> - depends on the platform
> - Mac
> - pre Snow Leopard
> - checks VM path and common library paths
> - Snow Leopard
> - only looks in VM bundle's Resources file, you must either :
> - store all external libraries there
> - ln -s path/to/library path/to/VM/Resources/library_name
> - Change the VM's Info.plist "SqueakPluginsBuiltInOrLocalOnly" key from
> "true" to "false."
> - security
> - malicious users could call arbitrary functions in the OS e.g. "format
> c:" from "system.dll" 
> - VMs do not protect against buffer overflow from bad parameters :
> "this would require an attacker to execute arbitrary Smalltalk
> code on your server. Of course if they can do that they own you
> anyway, especially if you allow FFi or use the OSProcess plugin" - John
> * difficulty
> - if you make a mistake you'll not drop into the debugger but Squeak will
> just crash 
> - If you crash Squeak when it is running the garbage collector, then you
> know your FFI code is leaking bits into object memory 
> What do I need to use FFI with Squeak?
> You need the FFI plugin, which is included with most VM's as of Squeak 3.6
> or so.
> You can also build the plugin yourself. See VMMaker.
>  http://wiki.squeak.org/squeak/1414
>  http://wiki.squeak.org/squeak/2424
>  http://wiki.squeak.org/squeak/5716
>  http://wiki.squeak.org/squeak/2426
>  http://wiki.squeak.org/squeak/5846
>  http://forum.world.st/FFI-Callbacks-td54056.html#a54073
>  http://forum.world.st/Security-td99624.html#a99635:
> Other choices:
> In the fall of 2008, Alien the FFI interface (written by Cadence Design
> Systems, Inc.) was put into squeaksource:
> http://www.squeaksource.com/Alien.html. This API allows the primitive to
> call back to Smalltalk Code, and return error code information, and
> apparently is much faster due to a less complex call sequence.
> * if you need callbacks
> * mac-only?
> Plugins - write external code and dynamically link it to the VM
> * safest - users are limited to using the functionality you provide and
> can not call other external functions e.g. system rm /
> * fast - faster than FFI
> * you can create new functionality that doesn't exist in any library
> * harder to write
> * plugin must be distributed with the Smalltalk code - there can be
> complications with platforms
> Primitive method - invokes behavior in the VM or a plugin 
> * why would you want to build the FFI plugin yourself?
> * api prefix or no for method names?
> * not sure about pre Snow Leopard library search
> * OSProcess - how does this fit into the bigger picture?
> * "^self externalCallFailed." or "self externalCallFailed." i.e. return self
> or return the result, or doesn't matter?
> * why would a field description have three elements?
> * Mac Memory Allocation Issues?
> View this message in context: http://forum.world.st/FFI-Documentation-tp2225148p2225148.html
> Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
> Pharo-project mailing list
> Pharo-project at lists.gforge.inria.fr
More information about the Pharo-project