mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-11 13:29:18 +02:00
+ add headers for the ffi library, the foreign function call library
git-svn-id: trunk@37084 -
This commit is contained in:
parent
7b675b6769
commit
0140028d4e
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -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
|
||||
|
102
packages/libffi/Makefile.fpc
Normal file
102
packages/libffi/Makefile.fpc
Normal 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
|
33
packages/libffi/examples/simple.pp
Normal file
33
packages/libffi/examples/simple.pp
Normal 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
41
packages/libffi/fpmake.pp
Normal 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
601
packages/libffi/src/ffi.pp
Normal 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.
|
Loading…
Reference in New Issue
Block a user