libffi/libffi.nim
Joey 994262b3cb
Update libffi to work with latest version
Libffi made some changes to their dll api. They no longer expose `ffi_type_longdouble`, but instead, offer it in a header like so:

```c
#define ffi_type_longdouble ffi_type_double
```

Also, `elements` is listed as a `ptr ptr` in the `ffi.h` file, but when used, it is apparent that it's supposed to be a pointer to an array of pointers.
2022-08-22 10:09:23 -06:00

173 lines
5.1 KiB
Nim

#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "LICENSE.txt", included in this
# distribution, for details about the copyright.
#
{.deadCodeElim: on.}
when defined(nimHasStyleChecks):
{.push styleChecks: off.}
when defined(windows):
import os
const libPath = currentSourcePath.parentDir / "libs"
when defined(cpu64):
const arch = "win64"
else:
const arch = "win32"
{.pragma: mylib, dynlib: libPath / arch / "libffi-7.dll".}
elif defined(macosx):
{.pragma: mylib, dynlib: "libffi.dylib".}
else:
{.pragma: mylib, dynlib: "libffi.so(.7|)".}
type
Arg* = int
SArg* = int
{.deprecated: [TArg: Arg, TSArg: SArg].}
when defined(windows) and defined(x86):
type
TABI* {.size: sizeof(cint).} = enum
FIRST_ABI, SYSV, STDCALL
const DEFAULT_ABI* = SYSV
elif defined(amd64) and defined(windows):
type
TABI* {.size: sizeof(cint).} = enum
FIRST_ABI, WIN64
const DEFAULT_ABI* = WIN64
else:
type
TABI* {.size: sizeof(cint).} = enum
FIRST_ABI, SYSV, UNIX64
when defined(i386):
const DEFAULT_ABI* = SYSV
else:
const DEFAULT_ABI* = UNIX64
const
tkVOID* = 0
tkINT* = 1
tkFLOAT* = 2
tkDOUBLE* = 3
tkLONGDOUBLE* = 4
tkUINT8* = 5
tkSINT8* = 6
tkUINT16* = 7
tkSINT16* = 8
tkUINT32* = 9
tkSINT32* = 10
tkUINT64* = 11
tkSINT64* = 12
tkSTRUCT* = 13
tkPOINTER* = 14
tkLAST = tkPOINTER
tkSMALL_STRUCT_1B* = (tkLAST + 1)
tkSMALL_STRUCT_2B* = (tkLAST + 2)
tkSMALL_STRUCT_4B* = (tkLAST + 3)
type
Type* = object
size*: int
alignment*: uint16
typ*: uint16
elements*: ptr UncheckedArray[ptr Type]
{.deprecated: [TType: Type].}
var
type_void* {.importc: "ffi_type_void", mylib.}: Type
type_uint8* {.importc: "ffi_type_uint8", mylib.}: Type
type_sint8* {.importc: "ffi_type_sint8", mylib.}: Type
type_uint16* {.importc: "ffi_type_uint16", mylib.}: Type
type_sint16* {.importc: "ffi_type_sint16", mylib.}: Type
type_uint32* {.importc: "ffi_type_uint32", mylib.}: Type
type_sint32* {.importc: "ffi_type_sint32", mylib.}: Type
type_uint64* {.importc: "ffi_type_uint64", mylib.}: Type
type_sint64* {.importc: "ffi_type_sint64", mylib.}: Type
type_float* {.importc: "ffi_type_float", mylib.}: Type
type_double* {.importc: "ffi_type_double", mylib.}: Type
type_pointer* {.importc: "ffi_type_pointer", mylib.}: Type
type_longdouble* {.importc: "ffi_type_double", mylib.}: Type
type
Status* {.size: sizeof(cint).} = enum
OK, BAD_TYPEDEF, BAD_ABI
TypeKind* = cuint
TCif* {.pure, final.} = object
abi*: TABI
nargs*: cuint
argTypes*: ptr ptr Type
rtype*: ptr Type
bytes*: cuint
flags*: cuint
{.deprecated: [Tstatus: Status].}
type
Raw* = object
sint*: SArg
{.deprecated: [TRaw: Raw].}
proc raw_call*(cif: var TCif; fn: proc () {.cdecl.}; rvalue: pointer;
avalue: ptr Raw) {.cdecl, importc: "ffi_raw_call", mylib.}
proc ptrarray_to_raw*(cif: var TCif; args: ptr pointer; raw: ptr Raw) {.cdecl,
importc: "ffi_ptrarray_to_raw", mylib.}
proc raw_to_ptrarray*(cif: var TCif; raw: ptr Raw; args: ptr pointer) {.cdecl,
importc: "ffi_raw_to_ptrarray", mylib.}
proc raw_size*(cif: var TCif): int {.cdecl, importc: "ffi_raw_size", mylib.}
proc prep_cif*(cif: var TCif; abi: TABI; nargs: cuint; rtype: ptr Type;
atypes: ptr ptr Type): Status {.cdecl, importc: "ffi_prep_cif",
mylib.}
proc call*(cif: var TCif; fn: proc () {.cdecl.}; rvalue: pointer;
avalue: ptr pointer) {.cdecl, importc: "ffi_call", mylib.}
# the same with an easier interface:
type
ParamList* = array[0..100, ptr Type]
ArgList* = array[0..100, pointer]
{.deprecated: [TParamList: ParamList, TArgList: ArgList].}
proc prep_cif*(cif: var TCif; abi: TABI; nargs: cuint; rtype: ptr Type;
atypes: ParamList): Status {.cdecl, importc: "ffi_prep_cif",
mylib.}
proc call*(cif: var TCif; fn, rvalue: pointer;
avalue: ArgList) {.cdecl, importc: "ffi_call", mylib.}
when defined(x8664):
const TRAMPOLINE_SIZE = 24
elif defined(windows) and defined(x86):
const TRAMPOLINE_SIZE = 52
elif defined(amd64) and defined(windows):
const TRAMPOLINE_SIZE = 29
else:
const TRAMPOLINE_SIZE = 10
type
ClosureProc = proc (cif: var TCif, ret: pointer, args: UncheckedArray[pointer], user_data: pointer) {.cdecl.}
Closure* {.pure, final.} = object
tramp: array[0..TRAMPOLINE_SIZE, uint8]
cif: ptr TCif
fun: ClosureProc
user_data: pointer
proc closure_alloc*(size: int, code: var pointer): ptr Closure {.cdecl, importc: "ffi_closure_alloc", mylib.}
# same but taking care of the size
template closure_alloc*(code: var pointer): ptr Closure =
closure_alloc(sizeof(Closure), code)
proc closure_free*(closure: ptr Closure) {.cdecl, importc: "ffi_closure_free", mylib.}
proc prep_closure_loc*(closure: ptr Closure, cif: var TCif, fun: ClosureProc, user_data: pointer, codeloc: pointer): Status {.cdecl, importc: "ffi_prep_closure_loc", mylib.}
# Useful for eliminating compiler warnings
##define FFI_FN(f) ((void (*)(void))f)
when defined(nimHasStyleChecks):
{.pop.} # {.push styleChecks: off.}