+ add headers for the ffi library, the foreign function call library

git-svn-id: trunk@37084 -
This commit is contained in:
svenbarth 2017-08-30 19:28:56 +00:00
parent 7b675b6769
commit 0140028d4e
5 changed files with 781 additions and 0 deletions

4
.gitattributes vendored
View File

@ -5175,6 +5175,10 @@ packages/libenet/src/enetprotocol.pp svneol=native#text/plain
packages/libenet/src/enettime.pp svneol=native#text/plain
packages/libenet/src/enettypes.pp svneol=native#text/plain
packages/libenet/src/uenetclass.pp svneol=native#text/plain
packages/libffi/Makefile.fpc svneol=native#text/plain
packages/libffi/examples/simple.pp svneol=native#text/pascal
packages/libffi/fpmake.pp svneol=native#text/pascal
packages/libffi/src/ffi.pp svneol=native#text/pascal
packages/libfontconfig/Makefile svneol=native#text/plain
packages/libfontconfig/Makefile.fpc svneol=native#text/plain
packages/libfontconfig/examples/testfc.lpi svneol=native#text/plain

View File

@ -0,0 +1,102 @@
#
# Makefile.fpc for running fpmake
#
[package]
name=libffi
version=3.1.1
[require]
packages=rtl fpmkunit
[install]
fpcpackage=y
[default]
fpcdir=../..
[prerules]
FPMAKE_BIN_CLEAN=$(wildcard ./fpmake$(SRCEXEEXT))
ifdef OS_TARGET
FPC_TARGETOPT+=--os=$(OS_TARGET)
endif
ifdef CPU_TARGET
FPC_TARGETOPT+=--cpu=$(CPU_TARGET)
endif
LOCALFPMAKE=./fpmake$(SRCEXEEXT)
[rules]
# Do not pass the Makefile's unit and binary target locations. Fpmake uses it's own.
override FPCOPT:=$(filter-out -FU%,$(FPCOPT))
override FPCOPT:=$(filter-out -FE%,$(FPCOPT))
# Do not pass the package-unitdirectories. Fpmake adds those and this way they don't apear in the .fpm
override FPCOPT:=$(filter-out $(addprefix -Fu,$(COMPILER_UNITDIR)),$(FPCOPT))# Compose general fpmake-parameters
# Compose general fpmake-parameters
ifdef FPMAKEOPT
FPMAKE_OPT+=$(FPMAKEOPT)
endif
FPMAKE_OPT+=--localunitdir=../..
FPMAKE_OPT+=--globalunitdir=..
FPMAKE_OPT+=$(FPC_TARGETOPT)
FPMAKE_OPT+=$(addprefix -o ,$(FPCOPT))
FPMAKE_OPT+=--compiler=$(FPC)
FPMAKE_OPT+=-bu
.NOTPARALLEL:
fpmake$(SRCEXEEXT): fpmake.pp
$(FPCFPMAKE) fpmake.pp $(FPMAKE_SKIP_CONFIG) $(addprefix -Fu,$(COMPILER_FPMAKE_UNITDIR)) $(FPCMAKEOPT) $(OPT)
all: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) compile $(FPMAKE_OPT)
smart: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -XX -o -CX
release: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dRELEASE
debug: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dDEBUG
# If no fpmake exists and (dist)clean is called, do not try to build fpmake, it will
# most often fail because the dependencies are cleared.
# In case of a clean, simply do nothing
ifeq ($(FPMAKE_BIN_CLEAN),)
clean:
else
clean:
$(FPMAKE_BIN_CLEAN) clean $(FPMAKE_OPT)
endif
# In case of a distclean, perform an 'old'-style distclean. This to avoid problems
# when the package is compiled using fpcmake prior to running this clean using fpmake
ifeq ($(FPMAKE_BIN_CLEAN),)
distclean: $(addsuffix _distclean,$(TARGET_DIRS)) fpc_cleanall
else
distclean:
ifdef inUnix
{ $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT); if [ $$? != "0" ]; then { echo Something wrong with fpmake exectable. Remove the executable and call make recursively to recover.; $(DEL) $(FPMAKE_BIN_CLEAN); $(MAKE) fpc_cleanall; }; fi; }
else
$(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT)
endif
-$(DEL) $(LOCALFPMAKE)
endif
cleanall: distclean
install: fpmake$(SRCEXEEXT)
ifdef UNIXHier
$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR)
else
$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR)
endif
# distinstall also installs the example-sources and omits the location of the source-
# files from the fpunits.cfg files.
distinstall: fpmake$(SRCEXEEXT)
ifdef UNIXHier
$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
else
$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
endif
zipinstall: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX)
zipdistinstall: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) -ie -fsp 0
zipsourceinstall: fpmake$(SRCEXEEXT)
ifdef UNIXHier
$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=share/src/fpc-\$$\(PACKAGEVERSION\)/$(INSTALL_FPCSUBDIR)/\$$\(PACKAGEDIRECTORY\)
else
$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=source\\$(INSTALL_FPCSUBDIR)\\\$$\(PACKAGEDIRECTORY\)
endif

View File

@ -0,0 +1,33 @@
program simple;
uses
ffi;
function WritePChar(s: PChar): LongInt; cdecl;
begin
Writeln(s);
WritePChar := StrLen(s);
end;
var
cif: ffi_cif;
args: array[0..0] of pffi_type;
values: array[0..0] of Pointer;
s: PChar;
rc: ffi_arg;
begin
args[0] := @ffi_type_pointer;
values[0] := @s;
if ffi_prep_cif(@cif, FFI_DEFAULT_ABI, 1, @ffi_type_sint, @args[0]) = FFI_OK then begin
s := 'Hello World';
ffi_call(@cif, ffi_fn(@WritePChar), @rc, @values[0]);
Writeln('Length: ', rc);
s := 'This is cool!';
ffi_call(@cif, ffi_fn(@WritePChar), @rc, @values[0]);
Writeln('Length: ', rc);
end else
Writeln('ffi_prep_cif failed');
end.

41
packages/libffi/fpmake.pp Normal file
View File

@ -0,0 +1,41 @@
{$ifndef ALLPACKAGES}
{$mode objfpc}{$H+}
program fpmake;
uses fpmkunit;
Var
P : TPackage;
T : TTarget;
begin
With Installer do
begin
{$endif ALLPACKAGES}
P:=AddPackage('libffi');
{$ifdef ALLPACKAGES}
P.Directory:=ADirectory;
{$endif ALLPACKAGES}
P.Version:='3.1.1';
P.Author := 'Anthony Green and others';
P.License := 'MIT license';
P.HomepageURL := 'https://sourceware.org/libffi/';
P.Email := 'libffi-discuss@sourceware.org';
P.Description := 'Headers for the libFFI library (Foreign Function Interface)';
P.NeedLibC:= true; // true for headers that indirectly link to libc?
P.OSes := [linux];
P.CPUs := [x86_64];
P.SourcePath.Add('src');
P.IncludePath.Add('src');
T:=P.Targets.AddUnit('ffi.pp');
P.ExamplePath.Add('examples');
P.Targets.AddExampleProgram('simple.pp');
{$ifndef ALLPACKAGES}
Run;
end;
end.
{$endif ALLPACKAGES}

601
packages/libffi/src/ffi.pp Normal file
View File

@ -0,0 +1,601 @@
(* -----------------------------------------------------------------*-C-*-
libffi 3.2.1 - Copyright (c) 2011, 2014 Anthony Green
- Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the ``Software''), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- *)
(* -------------------------------------------------------------------
The basic API is described in the README file.
The raw API is designed to bypass some of the argument packing
and unpacking on architectures for which it can be avoided.
The closure API allows interpreted functions to be packaged up
inside a C function pointer, so that they can be called as C functions,
with no understanding on the client side that they are interpreted.
It can also be used in other cases in which it is necessary to package
up a user specified parameter and a function pointer as a single
function pointer.
The closure API must be implemented in order to get its functionality,
e.g. for use by gij. Routines are provided to emulate the raw API
if the underlying platform doesn't allow faster implementation.
More details on the raw and cloure API can be found in:
http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
and
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-------------------------------------------------------------------- *)
unit ffi;
interface
uses
ctypes;
{
from the various ffitarget.h
}
{ ToDo: we need defines for the MIPS ABI }
const
{$if defined(CPUMIPS) or defined(CPU64)}
FFI_SIZEOF_ARG = 8;
{$else}
FFI_SIZEOF_ARG = 4;
{$endif}
FFI_SIZEOF_JAVA_ARG = FFI_SIZEOF_ARG;
{$if defined(CPUPOWERPC) and not defined(AIX) and not defined(DARWIN)}
{$if defined(CPUPOWERPC32)}
FFI_SYSV_SOFT_FLOAT = 1;
FFI_SYSV_STRUCT_RET = 2;
FFI_SYSV_IBM_LONG_DOUBLE = 4;
FFI_SYSV_LONG_DOUBLE_128 = 16;
{$elseif defined(CPUPOWERPC64)}
FFI_LINUX_STRUCT_ALIGN = 1;
FFI_LINUX_LONG_DOUBLE_128 = 2;
{$endif}
{$endif}
type
{$ifdef WIN64}
ffi_arg = QWord;
ffi_sarg = Int64;
{$else}
ffi_arg = culong;
ffi_sarg = cslong;
{$endif}
ffi_abi = (
FFI_FIRST_ABI,
{$if not defined(CPUMIPS) and not defined(CPUX86_64) and not defined(CPUPOWERPC) and not defined(CPUSPARCGEN)}
FFI_SYSV,
{$endif}
{$if defined(CPUARM)}
FFI_VFP,
{$endif}
{$if defined(CPUMIPS)}
FFI_O32,
FFI_N32,
FFI_N64,
FFI_O32_SOFT_FLOAT,
FFI_N32_SOFT_FLOAT,
FFI_N64_SOFT_FLOAT,
{$endif}
{$if defined(CPUX86_64)}
{$ifndef WIN64}
FFI_UNIX64,
{$endif}
FFI_WIN64,
{$endif}
{$if defined(CPUI386)}
{$ifdef WIN32}
FFI_STDCALL,
{$endif}
FFI_THISCALL = 3,
FFI_FASTCALL,
{$ifdef WIN32}
FFI_MS_CDECL,
{$else}
FFI_STDCALL,
{$endif}
FFI_PASCAL,
FFI_REGISTER,
{$endif}
{$if defined(CPUSPARC32)}
FFI_V8,
{$endif}
{$if defined(CPUSPARC64)}
FFI_V9,
{$endif}
{$if defined(CPUPOWERPC)}
{ this one is getting ugly... }
{$if defined(AIX) or defined(DARWIN)}
FFI_AIX,
FFI_DARWIN,
{$else}
FFI_COMPAT_SYSV,
FFI_COMPAT_GCC_SYSV,
FFI_COMPAT_LINUX64,
FFI_COMPAT_LINUX,
FFI_COMPAT_LINUX_SOFT_FLOAT,
{$if defined(CPUPOWERPC64)}
FFI_LINUX = 8,
{$define NO_LAST_ABI}
FFI_LAST_ABI = 12
{$elseif defined(CPUPOWERPC32)}
FFI_SYSV = 8,
{$define NO_LAST_ABI}
FFI_LAST_ABI = 32
{$endif}
{$endif}
{$endif}
{$ifndef NO_LAST_ABI}
FFI_LAST_ABI
{$endif}
);
{ alias values }
const
{$if defined(CPUX86_64) and not defined(WIN64)}
FFI_EFI64 = FFI_WIN64;
{$endif}
{$if defined(CPUARMHF)}
FFI_DEFAULT_ABI = FFI_VFP;
{$elseif defined(CPUMIPS)}
{ ToDo: needs define for ABI }
FFI_DEFAULT_ABI = FFI_N32;
{$elseif defined(CPUX86_64)}
{$ifdef WIN64}
FFI_DEFAULT_ABI = FFI_WIN64;
{$else}
FFI_DEFAULT_ABI = FFI_UNIX64;
{$endif}
{$elseif defined(CPUSPARC32)}
FFI_DEFAULT_ABI = FFI_V8;
{$elseif defined(CPUSPARC64)}
FFI_DEFAULT_ABI = FFI_V9;
{$elseif defined(CPUPOWERPC)}
{$if defined(AIX)}
FFI_DEFAULT_ABI = FFI_AIX;
{$elseif defined(DARWIN)}
FFI_DEFAULT_ABI = FFI_DARWIN;
{$elseif defined(CPUPOWERPC64)}
{ ToDo: find out what needs to be set }
FFI_DEFAULT_ABI = ffi_abi(Ord(FFI_LINUX) or FFI_LINUX_STRUCT_ALIGN or FFI_LINUX_LONG_DOUBLE_128);
{$elseif defined(CPUPOWERPC)}
{ ToDo: find out what needs to be set }
FFI_DEFAULT_ABI = ffi_abi(Ord(FFI_SYSV) {$ifdef FREEBSD}or FFI_SYSV_STRUCT_RET{$endif});
{$endif}
{$else}
FFI_DEFAULT_ABI = FFI_SYSV;
{$endif}
const
{$if defined(CPUPOWERPC)}
FFI_TARGET_HAS_COMPLEX_TYPE = False;
{$else}
FFI_TARGET_HAS_COMPLEX_TYPE = True;
{$endif}
(* ---- Definitions for closures ----------------------------------------- *)
const
FFI_CLOSURES = true;
{$if defined(DARWIN) and (defined(CPUARM) or defined(CPUAARCH64))}
FFI_EXEC_TRAMPOLINE_TABLE = True;
{$else}
FFI_EXEC_TRAMPOLINE_TABLE = False;
{$endif}
{$if defined(CPUI386)}
FFI_NATIVE_RAW_API = True;
{$else}
FFI_NATIVE_RAW_API = False;
{$endif}
{$if defined(CPUARM) or defined(CPUX86_64) or defined(CPUI386) or defined(CPUSPARCGEN) or (defined(CPUAARCH64) and not defined(DARWIN)) or (defined(CPUPOWERPC) and not defined(DARWIN))}
FFI_GO_CLOSURES = True;
{$else}
FFI_GO_CLOSURES = False;
{$endif}
{$if defined(CPUARM)}
{$if definde(DARWIN)}
FFI_TRAMPOLINE_SIZE = 12;
FFI_TRAMPOLINE_CLOSURE_OFFSET = 8;
{$elseif FFI_EXEC_TRAMPOLINE_TABLE}
{$error 'No trampoline table implementation'}
{$else}
FFI_TRAMPOLINE_SIZE = 12;
FFI_TRAMPOLINE_CLOSURE_OFFSET = FFI_TRAMPOLINE_SIZE;
{$endif}
{$elseif defined(CPUAARCH64)}
{$if defined(DARWIN)}
FFI_TRAMPOLINE_SIZE =16;
FFI_TRAMPOLINE_CLOSURE_OFFSET = 16;
{$elseif FFI_EXEC_TRAMPOLINE_TABLE}
{$error 'No trampoline table implementation'}
{$else}
FFI_TRAMPOLINE_SIZE = 24;
FFI_TRAMPOLINE_CLOSURE_OFFSET = FFI_TRAMPOLINE_SIZE;
{$endif}
{$elseif defined(CPUPOWERPC)}
{ ToDo: check for ELFv2? }
{$ifdef ELF_V2}
FFI_TRAMPOLINE_SIZE = 32;
{$else}
{$if defined(CPUPOWERPC64) or defined(AIX)}
{$if defined(DARWIN)}
FFI_TRAMPOLINE_SIZE = 48;
{$else}
FFI_TRAMPOLINE_SIZE = 25;
{$endif}
{$else}
FFI_TRAMPOLINE_SIZE = 40;
{$endif}
{$endif}
{$elseif defined(CPUSPARC32)}
FFI_TRAMPOLINE_SIZE = 16;
{$elseif defined(CPUSPARC64)}
FFI_TRAMPOLINE_SIZE = 24;
{$elseif defined(CPUX86_64)}
FFI_TRAMPOLINE_SIZE = 24;
{$elseif defined(CPUI386)}
FFI_TRAMPOLINE_SIZE = 12;
{$elseif defined(CPUM68K)}
FFI_TRAMPOLINE_SIZE = 16;
{$endif}
{
from ffi.h
}
const
ffilibrary = 'ffi';
{$if defined(CPUX86) and not defined(WIN64)}
{ Note: we can not use FPC_HAS_TYPE_EXTENDED here as libffi won't have the
corresponding type no matter what }
{$define HAVE_LONG_DOUBLE}
{$endif}
type
pffi_type = ^ffi_type;
ppffi_type = ^pffi_type;
ffi_type = record
size: csize_t;
alignment: cushort;
_type: cushort;
elements: ppffi_type;
end;
var
ffi_type_void: ffi_type; cvar; external ffilibrary;
ffi_type_uint8: ffi_type; cvar; external ffilibrary;
ffi_type_sint8: ffi_type; cvar; external ffilibrary;
ffi_type_uint16: ffi_type; cvar; external ffilibrary;
ffi_type_sint16: ffi_type; cvar; external ffilibrary;
ffi_type_uint32: ffi_type; cvar; external ffilibrary;
ffi_type_sint32: ffi_type; cvar; external ffilibrary;
ffi_type_uint64: ffi_type; cvar; external ffilibrary;
ffi_type_sint64: ffi_type; cvar; external ffilibrary;
ffi_type_float: ffi_type; cvar; external ffilibrary;
ffi_type_double: ffi_type; cvar; external ffilibrary;
ffi_type_pointer: ffi_type; cvar; external ffilibrary;
{$ifdef HAVE_LONG_DOUBLE}
ffi_type_longdouble: ffi_type; cvar; external ffilibrary;
{$else}
ffi_type_longdouble: ffi_type absolute ffi_type_double;
{$endif}
{$if FFI_TARGET_HAS_COMPLEX_TYPE}
ffi_type_complex_single: ffi_type; cvar; external ffilibrary;
ffi_type_complex_double: ffi_type; cvar; external ffilibrary;
{$ifdef HAVE_LONG_DOUBLE}
ffi_type_complex_longdouble: ffi_type; cvar; external ffilibrary;
{$endif}
{$endif}
{ type aliases }
ffi_type_uchar: ffi_type absolute ffi_type_uint8;
ffi_type_schar: ffi_type absolute ffi_type_sint8;
{ ToDo: check when C's short isn't 2 byte }
ffi_type_ushort: ffi_type absolute ffi_type_uint16;
ffi_type_sshort: ffi_type absolute ffi_type_sint16;
{ ToDo: check when C's int isn't 4 byte }
ffi_type_uint: ffi_type absolute ffi_type_uint32;
ffi_type_sint: ffi_type absolute ffi_type_sint32;
{$if defined(CPU64) and not defined(WIN64)}
ffi_type_ulong: ffi_type absolute ffi_type_uint64;
ffi_type_slong: ffi_type absolute ffi_type_sint64;
{$else}
ffi_type_ulong: ffi_type absolute ffi_type_uint32;
ffi_type_slong: ffi_type absolute ffi_type_sint32;
{$endif}
type
ffi_status = (
FFI_OK,
FFI_BAD_TYPEDEF,
FFI_BAD_ABI
);
pffi_cif = ^ffi_cif;
ffi_cif = record
abi: ffi_abi;
nargs: cunsigned;
arg_type: ppffi_type;
rtype: pffi_type;
bytes: cunsigned;
flags: cunsigned;
{$if defined(CPUARM)}
vfp_used: cint;
vfp_reg_free: cushort;
vfp_nargs: cushort;
vfp_args: array[0..15] of cchar;
{$elseif defined(CPUAARCH64)}
{$ifdef DARWIN}
aarch64_nfixedargs: cuint;
{$endif}
{$elseif defined(CPUSPARC64)}
nfixedargs: cuint;
{$elseif defined(CPUPOWERPC)}
{$ifndef DARWIN}
nfixedargs: cuint;
{$endif}
{$endif}
end;
pffi_raw = ^ffi_raw;
ffi_raw = record
case longint of
0: (sint: ffi_sarg);
1: (uint: ffi_arg);
2: (flt: cfloat);
3: (data: array[0..FFI_SIZEOF_ARG] of cchar);
4: (ptr: Pointer);
end;
{$if (FFI_SIZEOF_JAVA_ARG = 4) and (FFI_SIZEOF_ARG = 8)}
(* This is a special case for mips64/n32 ABI (and perhaps others) where
sizeof(void * ) is 4 and FFI_SIZEOF_ARG is 8. *)
ffi_java_raw = record
case longint of
0: (sint: ffi_sarg);
1: (uint: ffi_arg);
2: (flt: cfloat);
3: (data: array[0..FFI_SIZEOF_JAVA_ARG] of cchar);
4: (ptr: Pointer);
end;
{$else}
ffi_java_raw = ffi_raw;
{$endif}
pffi_java_raw = ^ffi_java_raw;
ffi_fn = procedure;
procedure ffi_raw_call(cif: pffi_cif;
fn: ffi_fn;
rvalue: Pointer;
avalue: pffi_raw); cdecl; external ffilibrary name 'ffi_raw_call';
procedure ffi_ptrarray_to_raw(cif: pffi_cif; args: PPointer; raw: pffi_raw); cdecl; external ffilibrary name 'ffi_ptrarray_to_raw';
procedure ffi_raw_to_ptrarray(cif: pffi_cif; raw: pffi_raw; args: PPointer); cdecl; external ffilibrary name 'ffi_raw_to_ptrarray';
function ffi_raw_size(cif: pffi_cif): csize_t; cdecl; external ffilibrary name 'ffi_raw_size';
(* This is analogous to the raw API, except it uses Java parameter
packing, even on 64-bit machines. I.e. on 64-bit machines longs
and doubles are followed by an empty 64-bit word. *)
procedure ffi_java_raw_call(cif: pffi_cif;
fn: ffi_fn;
rvalue: Pointer;
avalue: pffi_java_raw); cdecl; external ffilibrary name 'ffi_java_raw_call';
procedure ffi_java_ptrarray_to_raw(cif: pffi_cif; args: PPointer; raw: pffi_java_raw); cdecl; external ffilibrary name 'ffi_java_ptrarray_to_raw';
procedure ffi_java_raw_to_ptrarray(cif: pffi_cif; raw: pffi_java_raw; args: PPointer); cdecl; external ffilibrary name 'ffi_java_raw_to_ptrarray';
function ffi_java_raw_size(cif: pffi_cif): csize_t; cdecl; external ffilibrary name 'ffi_java_raw_size';
(* ---- Definitions for closures ----------------------------------------- *)
{$if FFI_CLOSURES}
type
ffi_closure_fun = procedure(cif: pffi_cif; arg1: Pointer; arg2: PPointer; arg3: Pointer); cdecl;
{ ToDo: align 8 }
ffi_closure = record
{$if FFI_EXEC_TRAMPOLINE_TABLE}
trampoline_table: Pointer;
trampoline_table_entry: Pointer;
{$else}
tramp: array[0..FFI_TRAMPOLINE_SIZE] of cchar;
{$endif}
cif: pffi_cif;
fun: ffi_closure_fun;
user_data: Pointer;
end;
pffi_closure = ^ffi_closure;
function ffi_closure_alloc(size: csize_t; code: PPointer): Pointer; cdecl; external ffilibrary name 'ffi_closure_alloc';
procedure ffi_closure_free(clo: Pointer); cdecl; external ffilibrary name 'ffi_closure_free';
function ffi_prep_closure(clo: pffi_closure;
cif: pffi_cif;
fun: ffi_closure_fun;
user_data: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_closure'; deprecated 'use ffi_prep_closure_loc instead';
function ffi_prep_closure_loc(clo: pffi_closure;
cif: pffi_cif;
fun: ffi_closure_fun;
user_data: Pointer;
codeloc: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_closure_loc';
type
ffi_raw_closure_fun = procedure(cif: pffi_cif; arg1: Pointer; arg2: pffi_raw; arg3: Pointer); cdecl;
ffi_java_raw_closure_fun = procedure(cif: pffi_cif; arg1: Pointer; arg2: pffi_java_raw; arg3: Pointer); cdecl;
{ ToDo: pack 8 for __sgi aka MIPS? }
ffi_raw_closure = record
{$if FFI_EXEC_TRAMPOLINE_TABLE}
trampoline_table: Pointer;
trampoline_table_entry: Pointer;
{$else}
tramp: array[0..FFI_TRAMPOLINE_SIZE] of cchar;
{$endif}
cif: pffi_cif;
{$if not FFI_NATIVE_RAW_API}
(* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. *)
translate_args: ffi_closure_fun;
this_closure: Pointer;
{$endif}
fun: ffi_raw_closure_fun;
user_data: Pointer;
end;
pffi_raw_closure = ^ffi_raw_closure;
{ ToDo: pack 8 for __sgi aka MIPS? }
ffi_java_raw_closure = record
{$if FFI_EXEC_TRAMPOLINE_TABLE}
trampoline_table: Pointer;
trampoline_table_entry: Pointer;
{$else}
tramp: array[0..FFI_TRAMPOLINE_SIZE] of cchar;
{$endif}
cif: pffi_cif;
{$if not FFI_NATIVE_RAW_API}
(* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. *)
translate_args: ffi_closure_fun;
this_closure: Pointer;
{$endif}
fun: ffi_java_raw_closure_fun;
user_data: Pointer;
end;
pffi_java_raw_closure = ^ffi_java_raw_closure;
function ffi_prep_raw_closure(clo: pffi_raw_closure;
cif: pffi_cif;
fun: ffi_raw_closure_fun;
user_data: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_raw_closure';
function ffi_prep_raw_closure_loc(clo: pffi_raw_closure;
cif: pffi_cif;
fun: ffi_raw_closure_fun;
user_data: Pointer;
codeloc: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_raw_closure_loc';
function ffi_prep_java_raw_closure(clo: pffi_java_raw_closure;
cif: pffi_cif;
fun: ffi_java_raw_closure_fun;
user_data: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_java_raw_closure';
function ffi_prep_java_raw_closure_loc(clo: pffi_java_raw_closure;
cif: pffi_cif;
fun: ffi_java_raw_closure_fun;
user_data: Pointer;
codeloc: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_java_raw_closure_loc';
{$endif}
{$if FFI_GO_CLOSURES}
type
ffi_go_closure = record
tramp: Pointer;
cif: pffi_cif;
fun: ffi_closure_fun;
end;
pffi_go_closure = ^ffi_go_closure;
function ffi_prep_go_closure(clo: pffi_go_closure; cif: pffi_cif; fun: ffi_closure_fun): ffi_status; cdecl; external ffilibrary name 'ffi_prep_go_closure';
procedure ffi_call_go(cif: pffi_cif; fn: ffi_fn; rvalue: Pointer; avalue: PPointer; closure: Pointer); cdecl; external ffilibrary name 'ffi_call_go';
{$endif}
(* ---- Public interface definition -------------------------------------- *)
function ffi_prep_cif(cif: pffi_cif;
abi: ffi_abi;
nargs: cuint;
rtype: pffi_type;
atypes: ppffi_type): ffi_status; cdecl; external ffilibrary name 'ffi_prep_cif';
function ffi_prep_cif_var(cif: pffi_cif;
abi: ffi_abi;
nfixedargs: cuint;
ntotalargs: cuint;
rtype: pffi_type;
atypes: ppffi_type): ffi_status; cdecl; external ffilibrary name 'ffi_prep_cif_var';
procedure ffi_call(cif: pffi_cif;
fn: ffi_fn;
rvalue: Pointer;
avalue: PPointer); cdecl; external ffilibrary name 'ffi_call';
function ffi_get_struct_offsets(abi: ffi_abi; struct_type: pffi_type;
offsets: pcsize_t): ffi_status; cdecl; external ffilibrary name 'ffi_get_struct_offsets';
const
_FFI_TYPE_VOID = 0;
_FFI_TYPE_INT = 1;
_FFI_TYPE_FLOAT = 2;
_FFI_TYPE_DOUBLE = 3;
{$ifdef HAVE_LONG_DOUBLE}
_FFI_TYPE_LONGDOUBLE = 4;
{$else}
_FFI_TYPE_LONGDOUBLE = _FFI_TYPE_DOUBLE;
{$endif}
_FFI_TYPE_UINT8 = 5;
_FFI_TYPE_SINT8 = 6;
_FFI_TYPE_UINT16 = 7;
_FFI_TYPE_SINT16 = 8;
_FFI_TYPE_UINT32 = 9;
_FFI_TYPE_SINT32 = 10;
_FFI_TYPE_UINT64 = 11;
_FFI_TYPE_SINT64 = 12;
_FFI_TYPE_STRUCT = 13;
_FFI_TYPE_POINTER = 14;
_FFI_TYPE_COMPLEX = 15;
_FFI_TYPE_LAST = _FFI_TYPE_COMPLEX;
{ ToDo: can we do without the platform specific types? }
implementation
end.