Search
Categories
Documents
FFI - Perl Foreign Function Interface (Displayed) README
|
FFI - Perl Foreign Function Interface
FFI - Perl Foreign Function Interface
use FFI;
$addr = <address of a C function>
$signature = <function signature>
$ret = FFI::call($addr, $signature, ...);
$cb = FFI::callback($signature, sub {...});
$ret = FFI::call($addr, $signature, $cb->addr, ...);
This module provides a low-level foreign function interface to Perl. It allows
the calling of any function for which the user can supply an address and
calling signature. Furthermore, it provides a method of encapsulating Perl
subroutines as callback functions whose addresses can be passed to C code.
Function interfaces are defined by signatures. A function's signature is a
string which specifies the function's return type, argument types and calling
convention. The first character of the string is the function's calling
convention. This is one of
s The standard calling convention for dynamically linked functions
c The calling convention used by C functions
Note that on many platforms, these two calling conventions may be identical.
On the Windows platform, the s code corresponds to the stdcall calling
convention, which is used for most dynamic link libraries. The c code
corresponds to the cdecl calling convention, which is used for C functions,
such as those in the C runtime library.
The remaining characters of the string are the return type of the function,
followed by the argument types, in left-to-right order. Valid values are based
on the codes used for the pack function, namely
c A signed char value.
C An unsigned char value.
s A signed short value.
S An unsigned short value.
i A signed integer value.
I An unsigned integer value.
l A signed long value.
L An unsigned long value.
f A single-precision float.
d A double-precision float.
p A pointer.
v No value (only valid as a return type).
Note that all of the above codes refer to ``native'' format values.
The p code as an argument type simply passes the address of the Perl
value's memory to the foreign function. It is the caller's responsibility to
be sure that the called function does not overwrite memory outside that
allocated by Perl.
The p code as a return type treats the returned value as a null-terminated
string, and passes it back to Perl as such. There is currently no support for
functions which return pointers to structures, or to other blocks of memory
which do not contain strings, nor for functions which return memory which the
caller must free.
To pass pointers to strings, use the p code. Perl ensures that strings are
null-terminated for you. To pass pointers to structures, use pack. To pass
an arbitrary block of memory, use something like the following:
$buf = ' ' x 100;
# Use $buf via a 'p' parameter as a 100-byte memory block
At the present time, there is no direct support for passing pointers to
'native' types (like int). To work around this, use $buf = pack('i', 12);
to put an integer into a block of memory, then use the p pointer type, and
obtain any returned value using $n = unpack('i', $buf); In the future,
better support may be added (but remember that this is intended as a low-level
interface!)
It is somewhat difficult to provide examples of using this module in
isolation, as it is necessary to (somehow) obtain the address of a function to
call. In general, this task is delegated to higher-level wrapper modules.
However, the standard DynaLoader module returns symbol references via the
DynaLoader::dl_find_symbol() function. While these references are not
documented as being addresses, in practice, they seem to be. Code to obtain
the address of various C library functions can be built around this
$clib_file = ($^O eq "MSWin32") ? "MSVCRT40.DLL" : "-lc";
$clib = DynaLoader::dl_findfile($clib_file);
$strlen = DynaLoader::dl_find_symbol($clib, "strlen");
$n = FFI::call($strlen, "cIp", $my_string);
DynaLoader::dl_free_file($clib);
Clearly, code like this needs to be encapsulated in a module of some form...
NOTE: In fact, the DynaLoader interface has problems in ActiveState Perl, and
probably in other binary distributions of Perl. (The issue is related to the
way in which the DynaLoader module is built, and may be addressed in future
versions of Perl). In the interim, the higher-level wrapper module
FFI::Library does not use DynaLoader on Win32 - it uses the (deprecated, but
still available) Win32::LoadLibrary and related calls.
Improve support for returning pointers to things other than null-terminated
strings.
Possibly, improve support for passing pointers to ``native'' types.
Substantial portions of the code for this module (the underlying FFI code) are
licensed under the Gnu General Public License. Under the terms of that
license, my understanding is that this module has to be distrubuted under that
same license.
My personal preference would be to distribute this module under the same terms
as Perl. However, I understand that this is not possible, given the licensing
of the FFI code.
Paul Moore, gustav@morpheus.demon.co.uk
http://clisp.cons.org/~haible/clisp.html
Bruno Haible's CLisp Common Lisp implementation, from which the underlying
foreign function interface code was taken.
Information
|
This site is currently in testing, it is not yet operating using the full database. Until it is officially launched you may wish to visit Help-Site Computer Manuals. After launch, this site (HelpSpy) will replace Help-Site. Information about the spider which is currently trawling the Internet looking for links to add to this directory can be found here. |
|