Add man files and info file. Update README. Tag as 2.99.3.
This commit is contained in:
@@ -1,3 +1,20 @@
|
||||
2008-02-14 Anthony Green <green@redhat.com>
|
||||
|
||||
* README: Update.
|
||||
* libffi.info: New file.
|
||||
* doc/stamp-vti: New file.
|
||||
* configure.ac: Bump version to 2.99.3.
|
||||
* configure: Rebuilt.
|
||||
|
||||
2008-02-14 Anthony Green <green@redhat.com>
|
||||
|
||||
* Makefile.am (SUBDIRS): Add man dir.
|
||||
* Makefile.in: Rebuilt.
|
||||
* configure.ac: Create Makefile.
|
||||
* configure: Rebuilt.
|
||||
* man/ffi_call.3 man/ffi_prep_cif.3 man/ffi_prep_closure.3
|
||||
man/Makefile.am man/Makefile.in: New files.
|
||||
|
||||
2008-02-14 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* aclocal.m4, Makefile.in, configure, fficonfig.h.in: Rebuilt.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
|
||||
SUBDIRS = include testsuite
|
||||
SUBDIRS = include testsuite man
|
||||
|
||||
EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host \
|
||||
src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \
|
||||
|
||||
@@ -60,7 +60,7 @@ subdir = .
|
||||
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/doc/stamp-vti \
|
||||
$(srcdir)/doc/version.texi $(srcdir)/fficonfig.h.in \
|
||||
$(srcdir)/libffi.pc.in $(top_srcdir)/configure ChangeLog \
|
||||
$(srcdir)/libffi.pc.in $(top_srcdir)/configure ChangeLog TODO \
|
||||
compile config.guess config.sub depcomp install-sh ltcf-c.sh \
|
||||
ltcf-cxx.sh ltcf-gcj.sh ltconfig ltmain.sh mdate-sh missing \
|
||||
mkinstalldirs texinfo.tex
|
||||
@@ -331,7 +331,7 @@ toolexeclibdir = @toolexeclibdir@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
SUBDIRS = include testsuite
|
||||
SUBDIRS = include testsuite man
|
||||
EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host \
|
||||
src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \
|
||||
src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \
|
||||
|
||||
288
libffi/README
288
libffi/README
@@ -36,38 +36,21 @@ exist above libffi that handles type conversions for values passed
|
||||
between the two languages.
|
||||
|
||||
|
||||
Supported Platforms and Prerequisites
|
||||
=====================================
|
||||
Supported Platforms
|
||||
===================
|
||||
|
||||
Libffi has been ported to:
|
||||
|
||||
SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9)
|
||||
|
||||
Irix 5.3 & 6.2 (System V/o32 & n32)
|
||||
|
||||
Intel x86 - Linux (System V ABI)
|
||||
|
||||
Alpha - Linux and OSF/1
|
||||
|
||||
m68k - Linux (System V ABI)
|
||||
|
||||
PowerPC - Linux (System V ABI, Darwin, AIX)
|
||||
|
||||
ARM - Linux (System V ABI)
|
||||
|
||||
Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are
|
||||
that other versions will work. Libffi has also been built and tested
|
||||
with the SGI compiler tools.
|
||||
|
||||
On PowerPC, the tests failed (see the note below).
|
||||
|
||||
You must use GNU make to build libffi. SGI's make will not work.
|
||||
Sun's probably won't either.
|
||||
|
||||
If you port libffi to another platform, please let me know! I assume
|
||||
that some will be easy (x86 NetBSD), and others will be more difficult
|
||||
(HP).
|
||||
Libffi has been ported to many different platforms, although this
|
||||
release was only tested on:
|
||||
|
||||
arm oabi linux
|
||||
arm eabi linux
|
||||
hppa64 linux
|
||||
powerpc64 linux
|
||||
sparc solaris (SPARC V9 ABI)
|
||||
x86 cygwin
|
||||
x86 linux
|
||||
x86-64 linux
|
||||
|
||||
|
||||
Installing libffi
|
||||
=================
|
||||
@@ -104,195 +87,6 @@ To ensure that libffi is working as advertised, type "make test".
|
||||
To install the library and header files, type "make install".
|
||||
|
||||
|
||||
Using libffi
|
||||
============
|
||||
|
||||
The Basics
|
||||
----------
|
||||
|
||||
Libffi assumes that you have a pointer to the function you wish to
|
||||
call and that you know the number and types of arguments to pass it,
|
||||
as well as the return type of the function.
|
||||
|
||||
The first thing you must do is create an ffi_cif object that matches
|
||||
the signature of the function you wish to call. The `cif' in ffi_cif
|
||||
stands for Call InterFace. To prepare a call interface object, use the
|
||||
following function:
|
||||
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
|
||||
unsigned int nargs,
|
||||
ffi_type *rtype, ffi_type **atypes);
|
||||
|
||||
CIF is a pointer to the call interface object you wish
|
||||
to initialize.
|
||||
|
||||
ABI is an enum that specifies the calling convention
|
||||
to use for the call. FFI_DEFAULT_ABI defaults
|
||||
to the system's native calling convention. Other
|
||||
ABI's may be used with care. They are system
|
||||
specific.
|
||||
|
||||
NARGS is the number of arguments this function accepts.
|
||||
libffi does not yet support vararg functions.
|
||||
|
||||
RTYPE is a pointer to an ffi_type structure that represents
|
||||
the return type of the function. Ffi_type objects
|
||||
describe the types of values. libffi provides
|
||||
ffi_type objects for many of the native C types:
|
||||
signed int, unsigned int, signed char, unsigned char,
|
||||
etc. There is also a pointer ffi_type object and
|
||||
a void ffi_type. Use &ffi_type_void for functions that
|
||||
don't return values.
|
||||
|
||||
ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long.
|
||||
If NARGS is 0, this is ignored.
|
||||
|
||||
|
||||
ffi_prep_cif will return a status code that you are responsible
|
||||
for checking. It will be one of the following:
|
||||
|
||||
FFI_OK - All is good.
|
||||
|
||||
FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif
|
||||
came across is bad.
|
||||
|
||||
|
||||
Before making the call, the VALUES vector should be initialized
|
||||
with pointers to the appropriate argument values.
|
||||
|
||||
To call the the function using the initialized ffi_cif, use the
|
||||
ffi_call function:
|
||||
|
||||
void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
|
||||
|
||||
CIF is a pointer to the ffi_cif initialized specifically
|
||||
for this function.
|
||||
|
||||
FN is a pointer to the function you want to call.
|
||||
|
||||
RVALUE is a pointer to a chunk of memory that is to hold the
|
||||
result of the function call. Currently, it must be
|
||||
at least one word in size (except for the n32 version
|
||||
under Irix 6.x, which must be a pointer to an 8 byte
|
||||
aligned value (a long long). It must also be at least
|
||||
word aligned (depending on the return type, and the
|
||||
system's alignment requirements). If RTYPE is
|
||||
&ffi_type_void, this is ignored. If RVALUE is NULL,
|
||||
the return value is discarded.
|
||||
|
||||
AVALUES is a vector of void* that point to the memory locations
|
||||
holding the argument values for a call.
|
||||
If NARGS is 0, this is ignored.
|
||||
|
||||
|
||||
If you are expecting a return value from FN it will have been stored
|
||||
at RVALUE.
|
||||
|
||||
|
||||
|
||||
An Example
|
||||
----------
|
||||
|
||||
Here is a trivial example that calls puts() a few times.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ffi.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[1];
|
||||
void *values[1];
|
||||
char *s;
|
||||
int rc;
|
||||
|
||||
/* Initialize the argument info vectors */
|
||||
args[0] = &ffi_type_pointer;
|
||||
values[0] = &s;
|
||||
|
||||
/* Initialize the cif */
|
||||
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_uint, args) == FFI_OK)
|
||||
{
|
||||
s = "Hello World!";
|
||||
ffi_call(&cif, puts, &rc, values);
|
||||
/* rc now holds the result of the call to puts */
|
||||
|
||||
/* values holds a pointer to the function's arg, so to
|
||||
call puts() again all we need to do is change the
|
||||
value of s */
|
||||
s = "This is cool!";
|
||||
ffi_call(&cif, puts, &rc, values);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Aggregate Types
|
||||
---------------
|
||||
|
||||
Although libffi has no special support for unions or bit-fields, it is
|
||||
perfectly happy passing structures back and forth. You must first
|
||||
describe the structure to libffi by creating a new ffi_type object
|
||||
for it. Here is the definition of ffi_type:
|
||||
|
||||
typedef struct _ffi_type
|
||||
{
|
||||
unsigned size;
|
||||
short alignment;
|
||||
short type;
|
||||
struct _ffi_type **elements;
|
||||
} ffi_type;
|
||||
|
||||
All structures must have type set to FFI_TYPE_STRUCT. You may set
|
||||
size and alignment to 0. These will be calculated and reset to the
|
||||
appropriate values by ffi_prep_cif().
|
||||
|
||||
elements is a NULL terminated array of pointers to ffi_type objects
|
||||
that describe the type of the structure elements. These may, in turn,
|
||||
be structure elements.
|
||||
|
||||
The following example initializes a ffi_type object representing the
|
||||
tm struct from Linux's time.h:
|
||||
|
||||
struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
/* Those are for future use. */
|
||||
long int __tm_gmtoff__;
|
||||
__const char *__tm_zone__;
|
||||
};
|
||||
|
||||
{
|
||||
ffi_type tm_type;
|
||||
ffi_type *tm_type_elements[12];
|
||||
int i;
|
||||
|
||||
tm_type.size = tm_type.alignment = 0;
|
||||
tm_type.elements = &tm_type_elements;
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
tm_type_elements[i] = &ffi_type_sint;
|
||||
|
||||
tm_type_elements[9] = &ffi_type_slong;
|
||||
tm_type_elements[10] = &ffi_type_pointer;
|
||||
tm_type_elements[11] = NULL;
|
||||
|
||||
/* tm_type can now be used to represent tm argument types and
|
||||
return types for ffi_prep_cif() */
|
||||
}
|
||||
|
||||
|
||||
|
||||
Platform Specific Notes
|
||||
=======================
|
||||
|
||||
@@ -340,8 +134,6 @@ You must use GNU Make to build libffi on SGI platforms.
|
||||
The ARM port was performed on a NetWinder running ARM Linux ELF
|
||||
(2.0.31) and gcc 2.8.1.
|
||||
|
||||
|
||||
|
||||
PowerPC System V ABI
|
||||
--------------------
|
||||
|
||||
@@ -372,6 +164,9 @@ History
|
||||
|
||||
3.00 Feb-XX-08
|
||||
Many changes, mostly thanks to the GCC project.
|
||||
Cygnus Solutions is now Red Hat.
|
||||
|
||||
[10 years go by...]
|
||||
|
||||
1.20 Oct-5-98
|
||||
Raffaele Sena produces ARM port.
|
||||
@@ -456,34 +251,53 @@ History
|
||||
Authors & Credits
|
||||
=================
|
||||
|
||||
libffi was written by Anthony Green <green@cygnus.com>.
|
||||
libffi was originally written by Anthony Green <green@redhat.com>.
|
||||
|
||||
Portions of libffi were derived from Gianni Mariani's free gencall
|
||||
library for Silicon Graphics machines.
|
||||
The developers of the GNU Compiler Collection project have made
|
||||
innumerable valuable contributions. See the ChangeLog file for
|
||||
details.
|
||||
|
||||
Some of the ideas behind libffi were inspired by Gianni Mariani's free
|
||||
gencall library for Silicon Graphics machines.
|
||||
|
||||
The closure mechanism was designed and implemented by Kresten Krab
|
||||
Thorup.
|
||||
|
||||
The Sparc port was derived from code contributed by the fine folks at
|
||||
Visible Decisions Inc <http://www.vdi.com>. Further enhancements were
|
||||
made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>.
|
||||
Major processor architecture ports were contributed by the following
|
||||
developers:
|
||||
|
||||
The Alpha port was written by Richard Henderson at Cygnus Solutions.
|
||||
|
||||
Andreas Schwab ported libffi to m68k Linux and provided a number of
|
||||
bug fixes.
|
||||
|
||||
Geoffrey Keating ported libffi to the PowerPC.
|
||||
|
||||
Raffaele Sena ported libffi to the ARM.
|
||||
alpha Richard Henderson
|
||||
arm Raffaele Sena
|
||||
cris Simon Posnjak, Hans-Peter Nilsson
|
||||
frv Anthony Green
|
||||
ia64 Hans Boehm
|
||||
m32r Kazuhiro Inaoka
|
||||
m68k Andreas Schwab
|
||||
mips Anthony Green
|
||||
mips64 David Daney
|
||||
pa Randolph Chung
|
||||
powerpc Geoffrey Keating
|
||||
powerpc64 Jakub Jelinek
|
||||
s390 Gerhard Tonn, Ulrich Weigand
|
||||
sh Kaz Kojima
|
||||
sh64 Kaz Kojima
|
||||
sparc Anthony Green, Gordon Irlam
|
||||
x86 Anthony Green
|
||||
x86-64 Bo Thorsen
|
||||
|
||||
Jesper Skov and Andrew Haley both did more than their fair share of
|
||||
stepping through the code and tracking down bugs.
|
||||
|
||||
Thanks also to Tom Tromey for bug fixes and configuration help.
|
||||
Thanks also to Tom Tromey for bug fixes, documentation and
|
||||
configuration help.
|
||||
|
||||
Thanks to Jim Blandy, who provided some useful feedback on the libffi
|
||||
interface.
|
||||
|
||||
Andreas Tobler has done a tremendous amount of work on the testsuite.
|
||||
|
||||
The list above is almost certainly incomplete and inaccurate. I'm
|
||||
happy to make corrections or additions upon request.
|
||||
|
||||
If you have a problem, or have found a bug, please send a note to
|
||||
green@cygnus.com.
|
||||
green@redhat.com.
|
||||
|
||||
23
libffi/configure
vendored
23
libffi/configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.61 for libffi 2.99.2.
|
||||
# Generated by GNU Autoconf 2.61 for libffi 2.99.3.
|
||||
#
|
||||
# Report bugs to <http://gcc.gnu.org/bugs.html>.
|
||||
#
|
||||
@@ -728,8 +728,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='libffi'
|
||||
PACKAGE_TARNAME='libffi'
|
||||
PACKAGE_VERSION='2.99.2'
|
||||
PACKAGE_STRING='libffi 2.99.2'
|
||||
PACKAGE_VERSION='2.99.3'
|
||||
PACKAGE_STRING='libffi 2.99.3'
|
||||
PACKAGE_BUGREPORT='http://gcc.gnu.org/bugs.html'
|
||||
|
||||
# Factoring default headers for most tests.
|
||||
@@ -1457,7 +1457,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures libffi 2.99.2 to adapt to many kinds of systems.
|
||||
\`configure' configures libffi 2.99.3 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1528,7 +1528,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of libffi 2.99.2:";;
|
||||
short | recursive ) echo "Configuration of libffi 2.99.3:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1638,7 +1638,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
libffi configure 2.99.2
|
||||
libffi configure 2.99.3
|
||||
generated by GNU Autoconf 2.61
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
@@ -1652,7 +1652,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by libffi $as_me 2.99.2, which was
|
||||
It was created by libffi $as_me 2.99.3, which was
|
||||
generated by GNU Autoconf 2.61. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -2475,7 +2475,7 @@ fi
|
||||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='libffi'
|
||||
VERSION='2.99.2'
|
||||
VERSION='2.99.3'
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
@@ -22695,7 +22695,7 @@ ac_config_commands="$ac_config_commands src"
|
||||
ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h"
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files include/Makefile include/ffi.h Makefile testsuite/Makefile libffi.pc"
|
||||
ac_config_files="$ac_config_files include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc"
|
||||
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
@@ -23297,7 +23297,7 @@ exec 6>&1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by libffi $as_me 2.99.2, which was
|
||||
This file was extended by libffi $as_me 2.99.3, which was
|
||||
generated by GNU Autoconf 2.61. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -23354,7 +23354,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
libffi config.status 2.99.2
|
||||
libffi config.status 2.99.3
|
||||
configured by $0, generated by GNU Autoconf 2.61,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
@@ -23478,6 +23478,7 @@ do
|
||||
"include/ffi.h") CONFIG_FILES="$CONFIG_FILES include/ffi.h" ;;
|
||||
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
|
||||
"testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;;
|
||||
"man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
|
||||
"libffi.pc") CONFIG_FILES="$CONFIG_FILES libffi.pc" ;;
|
||||
|
||||
*) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
|
||||
|
||||
@@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
|
||||
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
AC_INIT([libffi], [2.99.2], [http://gcc.gnu.org/bugs.html])
|
||||
AC_INIT([libffi], [2.99.3], [http://gcc.gnu.org/bugs.html])
|
||||
AC_CONFIG_HEADERS([fficonfig.h])
|
||||
|
||||
AC_CANONICAL_SYSTEM
|
||||
@@ -352,6 +352,6 @@ test -d src/$TARGETDIR || mkdir src/$TARGETDIR
|
||||
|
||||
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
|
||||
|
||||
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile libffi.pc)
|
||||
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc)
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
533
libffi/doc/libffi.info
Normal file
533
libffi/doc/libffi.info
Normal file
@@ -0,0 +1,533 @@
|
||||
This is ../libffi/doc/libffi.info, produced by makeinfo version 4.11
|
||||
from ../libffi/doc/libffi.texi.
|
||||
|
||||
This manual is for Libffi, a portable foreign-function interface
|
||||
library.
|
||||
|
||||
Copyright (C) 2008 Red Hat, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2, or
|
||||
(at your option) any later version. A copy of the license is
|
||||
included in the section entitled "GNU General Public License".
|
||||
|
||||
|
||||
INFO-DIR-SECTION
|
||||
START-INFO-DIR-ENTRY
|
||||
* libffi: (libffi). Portable foreign-function interface library.
|
||||
END-INFO-DIR-ENTRY
|
||||
|
||||
|
||||
File: libffi.info, Node: Top, Next: Introduction, Up: (dir)
|
||||
|
||||
libffi
|
||||
******
|
||||
|
||||
This manual is for Libffi, a portable foreign-function interface
|
||||
library.
|
||||
|
||||
Copyright (C) 2008 Red Hat, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2, or
|
||||
(at your option) any later version. A copy of the license is
|
||||
included in the section entitled "GNU General Public License".
|
||||
|
||||
|
||||
* Menu:
|
||||
|
||||
* Introduction:: What is libffi?
|
||||
* Using libffi:: How to use libffi.
|
||||
* Missing Features:: Things libffi can't do.
|
||||
* Index:: Index.
|
||||
|
||||
|
||||
File: libffi.info, Node: Introduction, Next: Using libffi, Prev: Top, Up: Top
|
||||
|
||||
1 What is libffi?
|
||||
*****************
|
||||
|
||||
Compilers for high level languages generate code that follow certain
|
||||
conventions. These conventions are necessary, in part, for separate
|
||||
compilation to work. One such convention is the "calling convention".
|
||||
The calling convention is a set of assumptions made by the compiler
|
||||
about where function arguments will be found on entry to a function. A
|
||||
calling convention also specifies where the return value for a function
|
||||
is found. The calling convention is also sometimes called the "ABI" or
|
||||
"Application Binary Interface".
|
||||
|
||||
Some programs may not know at the time of compilation what arguments
|
||||
are to be passed to a function. For instance, an interpreter may be
|
||||
told at run-time about the number and types of arguments used to call a
|
||||
given function. `Libffi' can be used in such programs to provide a
|
||||
bridge from the interpreter program to compiled code.
|
||||
|
||||
The `libffi' library provides a portable, high level programming
|
||||
interface to various calling conventions. This allows a programmer to
|
||||
call any function specified by a call interface description at run time.
|
||||
|
||||
FFI stands for Foreign Function Interface. A foreign function
|
||||
interface is the popular name for the interface that allows code
|
||||
written in one language to call code written in another language. The
|
||||
`libffi' library really only provides the lowest, machine dependent
|
||||
layer of a fully featured foreign function interface. A layer must
|
||||
exist above `libffi' that handles type conversions for values passed
|
||||
between the two languages.
|
||||
|
||||
|
||||
File: libffi.info, Node: Using libffi, Next: Missing Features, Prev: Introduction, Up: Top
|
||||
|
||||
2 Using libffi
|
||||
**************
|
||||
|
||||
* Menu:
|
||||
|
||||
* The Basics:: The basic libffi API.
|
||||
* Simple Example:: A simple example.
|
||||
* Types:: libffi type descriptions.
|
||||
* Multiple ABIs:: Different passing styles on one platform.
|
||||
* The Closure API:: Writing a generic function.
|
||||
|
||||
|
||||
File: libffi.info, Node: The Basics, Next: Simple Example, Up: Using libffi
|
||||
|
||||
2.1 The Basics
|
||||
==============
|
||||
|
||||
`Libffi' assumes that you have a pointer to the function you wish to
|
||||
call and that you know the number and types of arguments to pass it, as
|
||||
well as the return type of the function.
|
||||
|
||||
The first thing you must do is create an `ffi_cif' object that
|
||||
matches the signature of the function you wish to call. This is a
|
||||
separate step because it is common to make multiple calls using a
|
||||
single `ffi_cif'. The "cif" in `ffi_cif' stands for Call InterFace.
|
||||
To prepare a call interface object, use the function `ffi_prep_cif'.
|
||||
|
||||
-- Function: ffi_status ffi_prep_cif (ffi_cif *CIF, ffi_abi ABI,
|
||||
unsigned int NARGS, ffi_type *RTYPE, ffi_type **ARGTYPES)
|
||||
This initializes CIF according to the given parameters.
|
||||
|
||||
ABI is the ABI to use; normally `FFI_DEFAULT_ABI' is what you
|
||||
want. *note Multiple ABIs:: for more information.
|
||||
|
||||
NARGS is the number of arguments that this function accepts.
|
||||
`libffi' does not yet handle varargs functions; see *note Missing
|
||||
Features:: for more information.
|
||||
|
||||
RTYPE is a pointer to an `ffi_type' structure that describes the
|
||||
return type of the function. *Note Types::.
|
||||
|
||||
ARGTYPES is a vector of `ffi_type' pointers. ARGTYPES must have
|
||||
NARGS elements. If NARGS is 0, this argument is ignored.
|
||||
|
||||
`ffi_prep_cif' returns a `libffi' status code, of type
|
||||
`ffi_status'. This will be either `FFI_OK' if everything worked
|
||||
properly; `FFI_BAD_TYPEDEF' if one of the `ffi_type' objects is
|
||||
incorrect; or `FFI_BAD_ABI' if the ABI parameter is invalid.
|
||||
|
||||
To call a function using an initialized `ffi_cif', use the
|
||||
`ffi_call' function:
|
||||
|
||||
-- Function: void ffi_call (ffi_cif *CIF, void *FN, void *RVALUE, void
|
||||
**AVALUES)
|
||||
This calls the function FN according to the description given in
|
||||
CIF. CIF must have already been prepared using `ffi_prep_cif'.
|
||||
|
||||
RVALUE is a pointer to a chunk of memory that will hold the result
|
||||
of the function call. This must be large enough to hold the
|
||||
result and must be suitably aligned; it is the caller's
|
||||
responsibility to ensure this. If CIF declares that the function
|
||||
returns `void' (using `ffi_type_void'), then RVALUE is ignored.
|
||||
If RVALUE is `NULL', then the return value is discarded.
|
||||
|
||||
AVALUES is a vector of `void *' pointers that point to the memory
|
||||
locations holding the argument values for a call. If CIF declares
|
||||
that the function has no arguments (i.e., NARGS was 0), then
|
||||
AVALUES is ignored.
|
||||
|
||||
|
||||
File: libffi.info, Node: Simple Example, Next: Types, Prev: The Basics, Up: Using libffi
|
||||
|
||||
2.2 Simple Example
|
||||
==================
|
||||
|
||||
Here is a trivial example that calls `puts' a few times.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ffi.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[1];
|
||||
void *values[1];
|
||||
char *s;
|
||||
int rc;
|
||||
|
||||
/* Initialize the argument info vectors */
|
||||
args[0] = &ffi_type_pointer;
|
||||
values[0] = &s;
|
||||
|
||||
/* Initialize the cif */
|
||||
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_uint, args) == FFI_OK)
|
||||
{
|
||||
s = "Hello World!";
|
||||
ffi_call(&cif, puts, &rc, values);
|
||||
/* rc now holds the result of the call to puts */
|
||||
|
||||
/* values holds a pointer to the function's arg, so to
|
||||
call puts() again all we need to do is change the
|
||||
value of s */
|
||||
s = "This is cool!";
|
||||
ffi_call(&cif, puts, &rc, values);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
File: libffi.info, Node: Types, Next: Multiple ABIs, Prev: Simple Example, Up: Using libffi
|
||||
|
||||
2.3 Types
|
||||
=========
|
||||
|
||||
* Menu:
|
||||
|
||||
* Primitive Types:: Built-in types.
|
||||
* Structures:: Structure types.
|
||||
* Type Example:: Structure type example.
|
||||
|
||||
|
||||
File: libffi.info, Node: Primitive Types, Next: Structures, Up: Types
|
||||
|
||||
2.3.1 Primitive Types
|
||||
---------------------
|
||||
|
||||
`Libffi' provides a number of built-in type descriptors that can be
|
||||
used to describe argument and return types:
|
||||
|
||||
`ffi_type_void'
|
||||
The type `void'. This cannot be used for argument types, only for
|
||||
return values.
|
||||
|
||||
`ffi_type_uint8'
|
||||
An unsigned, 8-bit integer type.
|
||||
|
||||
`ffi_type_sint8'
|
||||
A signed, 8-bit integer type.
|
||||
|
||||
`ffi_type_uint16'
|
||||
An unsigned, 16-bit integer type.
|
||||
|
||||
`ffi_type_sint16'
|
||||
A signed, 16-bit integer type.
|
||||
|
||||
`ffi_type_uint32'
|
||||
An unsigned, 32-bit integer type.
|
||||
|
||||
`ffi_type_sint32'
|
||||
A signed, 32-bit integer type.
|
||||
|
||||
`ffi_type_uint64'
|
||||
An unsigned, 64-bit integer type.
|
||||
|
||||
`ffi_type_sint64'
|
||||
A signed, 64-bit integer type.
|
||||
|
||||
`ffi_type_float'
|
||||
The C `float' type.
|
||||
|
||||
`ffi_type_double'
|
||||
The C `double' type.
|
||||
|
||||
`ffi_type_uchar'
|
||||
The C `unsigned char' type.
|
||||
|
||||
`ffi_type_schar'
|
||||
The C `signed char' type. (Note that there is not an exact
|
||||
equivalent to the C `char' type in `libffi'; ordinarily you should
|
||||
either use `ffi_type_schar' or `ffi_type_uchar' depending on
|
||||
whether `char' is signed.)
|
||||
|
||||
`ffi_type_ushort'
|
||||
The C `unsigned short' type.
|
||||
|
||||
`ffi_type_sshort'
|
||||
The C `short' type.
|
||||
|
||||
`ffi_type_uint'
|
||||
The C `unsigned int' type.
|
||||
|
||||
`ffi_type_sint'
|
||||
The C `int' type.
|
||||
|
||||
`ffi_type_ulong'
|
||||
The C `unsigned long' type.
|
||||
|
||||
`ffi_type_slong'
|
||||
The C `long' type.
|
||||
|
||||
`ffi_type_longdouble'
|
||||
On platforms that have a C `long double' type, this is defined.
|
||||
On other platforms, it is not.
|
||||
|
||||
`ffi_type_pointer'
|
||||
A generic `void *' pointer. You should use this for all pointers,
|
||||
regardless of their real type.
|
||||
|
||||
Each of these is of type `ffi_type', so you must take the address
|
||||
when passing to `ffi_prep_cif'.
|
||||
|
||||
|
||||
File: libffi.info, Node: Structures, Next: Type Example, Prev: Primitive Types, Up: Types
|
||||
|
||||
2.3.2 Structures
|
||||
----------------
|
||||
|
||||
Although `libffi' has no special support for unions or bit-fields, it
|
||||
is perfectly happy passing structures back and forth. You must first
|
||||
describe the structure to `libffi' by creating a new `ffi_type' object
|
||||
for it.
|
||||
|
||||
-- ffi_type:
|
||||
The `ffi_type' has the following members:
|
||||
`size_t size'
|
||||
This is set by `libffi'; you should initialize it to zero.
|
||||
|
||||
`unsigned short alignment'
|
||||
This is set by `libffi'; you should initialize it to zero.
|
||||
|
||||
`unsigned short type'
|
||||
For a structure, this should be set to `FFI_TYPE_STRUCT'.
|
||||
|
||||
`ffi_type **elements'
|
||||
This is a `NULL'-terminated array of pointers to `ffi_type'
|
||||
objects. There is one element per field of the struct.
|
||||
|
||||
|
||||
File: libffi.info, Node: Type Example, Prev: Structures, Up: Types
|
||||
|
||||
2.3.3 Type Example
|
||||
------------------
|
||||
|
||||
The following example initializes a `ffi_type' object representing the
|
||||
`tm' struct from Linux's `time.h'.
|
||||
|
||||
Here is how the struct is defined:
|
||||
|
||||
struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
/* Those are for future use. */
|
||||
long int __tm_gmtoff__;
|
||||
__const char *__tm_zone__;
|
||||
};
|
||||
|
||||
Here is the corresponding code to describe this struct to `libffi':
|
||||
|
||||
{
|
||||
ffi_type tm_type;
|
||||
ffi_type *tm_type_elements[12];
|
||||
int i;
|
||||
|
||||
tm_type.size = tm_type.alignment = 0;
|
||||
tm_type.elements = &tm_type_elements;
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
tm_type_elements[i] = &ffi_type_sint;
|
||||
|
||||
tm_type_elements[9] = &ffi_type_slong;
|
||||
tm_type_elements[10] = &ffi_type_pointer;
|
||||
tm_type_elements[11] = NULL;
|
||||
|
||||
/* tm_type can now be used to represent tm argument types and
|
||||
return types for ffi_prep_cif() */
|
||||
}
|
||||
|
||||
|
||||
File: libffi.info, Node: Multiple ABIs, Next: The Closure API, Prev: Types, Up: Using libffi
|
||||
|
||||
2.4 Multiple ABIs
|
||||
=================
|
||||
|
||||
A given platform may provide multiple different ABIs at once. For
|
||||
instance, the x86 platform has both `stdcall' and `fastcall' functions.
|
||||
|
||||
`libffi' provides some support for this. However, this is
|
||||
necessarily platform-specific.
|
||||
|
||||
|
||||
File: libffi.info, Node: The Closure API, Prev: Multiple ABIs, Up: Using libffi
|
||||
|
||||
2.5 The Closure API
|
||||
===================
|
||||
|
||||
`libffi' also provides a way to write a generic function - a function
|
||||
that can accept and decode any combination of arguments. This can be
|
||||
useful when writing an interpreter, or to provide wrappers for
|
||||
arbitrary functions.
|
||||
|
||||
This facility is called the "closure API". Closures are not
|
||||
supported on all platforms; you can check the `FFI_CLOSURES' define to
|
||||
determine whether they are supported on the current platform.
|
||||
|
||||
Because closures work by assembling a tiny function at runtime, they
|
||||
require special allocation on platforms that have a non-executable
|
||||
heap. Memory management for closures is handled by a pair of functions:
|
||||
|
||||
-- Function: void *ffi_closure_alloc (size_t SIZE, void **CODE)
|
||||
Allocate a chunk of memory holding SIZE bytes. This returns a
|
||||
pointer to the writable address, and sets *CODE to the
|
||||
corresponding executable address.
|
||||
|
||||
SIZE should be sufficient to hold a `ffi_closure' object.
|
||||
|
||||
-- Function: void ffi_closure_free (void *WRITABLE)
|
||||
Free memory allocated using `ffi_closure_alloc'. The argument is
|
||||
the writable address that was returned.
|
||||
|
||||
Once you have allocated the memory for a closure, you must construct
|
||||
a `ffi_cif' describing the function call. Finally you can prepare the
|
||||
closure function:
|
||||
|
||||
-- Function: ffi_status ffi_prep_closure_loc (ffi_closure *CLOSURE,
|
||||
ffi_cif *CIF, void (*FUN) (ffi_cif *CIF, void *RET, void
|
||||
**ARGS, void *USER_DATA), void *USER_DATA, void *CODELOC)
|
||||
Prepare a closure function.
|
||||
|
||||
CLOSURE is the address of a `ffi_closure' object; this is the
|
||||
writable address returned by `ffi_closure_alloc'.
|
||||
|
||||
CIF is the `ffi_cif' describing the function parameters.
|
||||
|
||||
USER_DATA is an arbitrary datum that is passed, uninterpreted, to
|
||||
your closure function.
|
||||
|
||||
CODELOC is the executable address returned by `ffi_closure_alloc'.
|
||||
|
||||
FUN is the function which will be called when the closure is
|
||||
invoked. It is called with the arguments:
|
||||
CIF
|
||||
The `ffi_cif' passed to `ffi_prep_closure_loc'.
|
||||
|
||||
RET
|
||||
A pointer to the memory used for the function's return value.
|
||||
FUN must fill this, unless the function is declared as
|
||||
returning `void'.
|
||||
|
||||
ARGS
|
||||
A vector of pointers to memory holding the arguments to the
|
||||
function.
|
||||
|
||||
USER_DATA
|
||||
The same USER_DATA that was passed to `ffi_prep_closure_loc'.
|
||||
|
||||
`ffi_prep_closure_loc' will return `FFI_OK' if everything went ok,
|
||||
and something else on error.
|
||||
|
||||
After calling `ffi_prep_closure_loc', you can cast CODELOC to the
|
||||
appropriate pointer-to-function type.
|
||||
|
||||
You may see old code referring to `ffi_prep_closure'. This function
|
||||
is deprecated, as it cannot handle the need for separate writable and
|
||||
executable addresses.
|
||||
|
||||
|
||||
File: libffi.info, Node: Missing Features, Next: Index, Prev: Using libffi, Up: Top
|
||||
|
||||
3 Missing Features
|
||||
******************
|
||||
|
||||
`libffi' is missing a few features. We welcome patches to add support
|
||||
for these.
|
||||
|
||||
* There is no support for calling varargs functions. This may work
|
||||
on some platforms, depending on how the ABI is defined, but it is
|
||||
not reliable.
|
||||
|
||||
* There is no support for bit fields in structures.
|
||||
|
||||
* The closure API is
|
||||
|
||||
* The "raw" API is undocumented.
|
||||
|
||||
|
||||
File: libffi.info, Node: Index, Prev: Missing Features, Up: Top
|
||||
|
||||
Index
|
||||
*****
|
||||
|
||||
| ||||