On 20 May 2010 22:25, St�phane Ducasse <
stephane.ducasse@inria.fr>
wrote:
> thanks sean
> this is cool to see such kind of
documentation emerging.
>
> Stef
>
> 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:
>>
>> FFI
>>
>> 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.[1]
>>
>> 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)
>>
>> Example:
>> 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
>>
convention)
>>
- 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):
>>
void
>>
bool
>>
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
[4]
>> - subclass of
ExternalStructure
>>
- class>>fields that returns an array of field descriptions (see
below)
>>
- Example:
>>
fields
>>
^#((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 [4]
>>
- 2-element array (or three but that does something else, I'm
not sure
>> what):
>>
- first element is the field name
>>
- second is the
type
>>
>> Mac Memory Allocation Issues [4] (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 [5]:
>>
- 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."
>> Caveats
>> -
security
>> -
malicious users could call arbitrary functions in the OS e.g.
"format
>> c:" from "system.dll" [7]
>>
- VMs do not protect against buffer
overflow from bad parameters [8]:
>>
"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
>>
McIntosh
>>
>> * difficulty
>>
- if you make a mistake you'll not drop into the debugger but Squeak
will
>> just crash [2]
>> - If you
crash Squeak when it is running the garbage collector, then you
>>
know your FFI code is leaking bits into object memory
[2]
>>
>> 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.
>>
>>
References:
>> [1]
http://wiki.squeak.org/squeak/1414>> [2]
http://wiki.squeak.org/squeak/2424>> [3]
http://wiki.squeak.org/squeak/5716>> [4]
http://wiki.squeak.org/squeak/2426>>
[5]
>>
http://forum.world.st/squeak-dev-Alien-Squeak-FFI-issues-on-Snow-Leopard-td85608.html>>
[6]
http://wiki.squeak.org/squeak/5846>> [7]
http://forum.world.st/FFI-Callbacks-td54056.html#a54073>>
[8]
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
>>
Pros:
>>
* 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
>>
Cons:
>>
* 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 [3]
>>
>>
Questions:
>> * 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@lists.gforge.inria.fr>>
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project>
>
>
_______________________________________________
> Pharo-project mailing
list
>
Pharo-project@lists.gforge.inria.fr>
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project>