Compare commits

...
Sign in to create a new pull request.

15 commits

Author SHA1 Message Date
Andreas Rumpf
bb2bdaf1a2
Merge pull request #10 from jyapayne/patch-1
Update libffi to work with latest version
2022-08-23 08:06:32 +02:00
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
Andreas Rumpf
153322d744
Merge pull request #6 from jyapayne/add_windows_dll
Add windows libffi.dll and remove old code
2021-08-24 08:13:16 +02:00
Andreas Rumpf
8cec577c92
Merge pull request #9 from SolitudeSF/dynlib
Correctly match dynlib
2021-03-02 12:46:44 +01:00
SolitudeSF
ea5f1f2b8e
Correctly match dynlib 2021-03-01 16:18:11 +02:00
Andreas Rumpf
5c3eab3abf
Merge pull request #8 from Arnaz87/closure
Fix wrong alllocation size for closure api
2020-11-30 18:21:40 +01:00
Arnaud Castellanos Galea
4bb54e221e 1.0.5 2020-11-30 17:25:36 +08:00
Arnaud Castellanos Galea
3c93bfdedc Fix wrong alllocation size for closure api 2020-11-30 17:25:28 +08:00
Araq
d5b23c4405 1.0.4 2020-10-06 15:32:34 +02:00
Araq
e3c08b54b8 added styleChecks:off 2020-10-06 15:32:25 +02:00
Araq
88401f510f 1.0.3 2020-10-06 15:08:05 +02:00
Andreas Rumpf
633cfb5b43
Merge pull request #7 from Arnaz87/closure
Closure API
2020-10-06 15:07:14 +02:00
Arnaud Castellanos Galea
e9c9c5c465 Increase library version number 2020-10-05 11:33:00 +08:00
Arnaud Castellanos Galea
4c880db828 Update Examples 2020-10-05 10:23:43 +08:00
Arnaud Castellanos Galea
b613920f1f Add support for closure api 2020-10-05 10:22:56 +08:00
4 changed files with 107 additions and 20 deletions

View file

@ -16,13 +16,16 @@ if dll == nil:
# Now let's try and get a symbol from it # Now let's try and get a symbol from it
var procSym = dll.symAddr("hello") var procSym = dll.symAddr("hello")
if procSym == nil:
echo "Could not get symbol for hello"
quit 1
# We need to set up our call first. This procedure takes one int argument # We need to set up our call first. This procedure takes one int argument
var var
cif: Tcif cif: Tcif
params: ParamList params: ParamList
# The argument the procedure takes # The argument the procedure takes
params[0] = type_sint64.addr params[0] = type_sint32.addr
# Prepare the call, with the aforementioned params, and no return type # Prepare the call, with the aforementioned params, and no return type
if OK != prep_cif(cif, DEFAULT_ABI, 1, type_void.addr, params): if OK != prep_cif(cif, DEFAULT_ABI, 1, type_void.addr, params):
echo "Something went wrong with preparing the statement" echo "Something went wrong with preparing the statement"
@ -30,14 +33,16 @@ if OK != prep_cif(cif, DEFAULT_ABI, 1, type_void.addr, params):
# Now let's set up a list of arguments # Now let's set up a list of arguments
var args: ArgList var args: ArgList
var i = 100 var i: int32 = 100
args[0] = i.addr args[0] = i.addr
# And call the symbol with our argument # And call the symbol with our argument
call(cif, procSym, nil, args) call(cif, procSym, nil, args)
# Let's do another one. This time without arguments, but with a return type # Let's do another one. This time without arguments, but with a return type
if OK != prep_cif(cif, DEFAULT_ABI, 0, type_sint64.addr, params): if OK != prep_cif(cif, DEFAULT_ABI, 0, type_sint32.addr, params):
echo "Something went wrong with preparing the statement" echo "Something went wrong with preparing the statement"
quit 1 quit 1
@ -45,7 +50,57 @@ if OK != prep_cif(cif, DEFAULT_ABI, 0, type_sint64.addr, params):
var highFiveSym = dll.symAddr("highFive") var highFiveSym = dll.symAddr("highFive")
# Set up the position of our return value and call the procedure # Set up the position of our return value and call the procedure
var theFive = 0 var theFive: int32 = 0
call(cif, highFiveSym, theFive.addr, args) call(cif, highFiveSym, theFive.addr, args)
echo theFive echo theFive
# And yet another example. This one with a simple function argument
params[0] = type_pointer.addr
if OK != prep_cif(cif, DEFAULT_ABI, 1, type_void.addr, params):
echo "Something went wrong with preparing the statement"
quit 1
var helloFancySym = dll.symAddr("helloFancy")
if helloFancySym == nil:
echo "Could not get symbol for helloFancy"
quit 1
# This is the function that will be called
proc fancyTen(x: int32): int32 {.cdecl.} =
result = 10
echo "It was given, ", x
var fancyTenPointer: pointer = fancyTen
args[0] = fancyTenPointer.addr
call(cif, helloFancySym, nil, args)
# Now, let's build a function at runtime with the closure API
proc uglyEleven(cif: var TCif, ret: pointer, args: UncheckedArray[pointer], user_data: pointer) {.cdecl.} =
#long int x = *(long int*)args[0];
var x = cast[ptr int32](args[0])[]
var c = cast[ptr int](user_data)[]
echo "Given: ", x, ", Context: ", c
cast[ptr int32](ret)[] = 11
var bound: pointer = nil
var closure: ptr Closure = closure_alloc(bound)
# Initialize the cif
if OK != prep_cif(cif, DEFAULT_ABI, 1, type_sint32.addr, params):
echo "Something went wrong with preparing the statement"
quit 1
var user_data = 17
if OK != prep_closure_loc(closure, cif, uglyEleven, user_data.addr, bound):
echo "Something went wrong initializing the closure"
quit 1
var r = cast[proc (x: int32): int32 {.cdecl.}](bound)(15)
echo "Result, ", r

View file

@ -1,7 +1,10 @@
# Compile with: nim c --noMain --app:lib plugin.nim # Compile with: nim c --noMain --app:lib plugin.nim
proc hello(x: int) {.exportc.} = proc hello(x: int32) {.cdecl, exportc, dynlib.} =
echo "Hello world, ", x echo "Hello world, ", x
proc highFive(): int {.exportc.} = proc highFive(): int32 {.cdecl, exportc, dynlib.} =
result = 5 result = 5
echo "Here you go!" echo "Here you go!"
proc helloFancy(f: proc (n: int32): int32 {.cdecl.}) {.exportc.} =
echo "Such fancyness, ", f(42)

View file

@ -8,6 +8,8 @@
# #
{.deadCodeElim: on.} {.deadCodeElim: on.}
when defined(nimHasStyleChecks):
{.push styleChecks: off.}
when defined(windows): when defined(windows):
import os import os
@ -23,7 +25,7 @@ when defined(windows):
elif defined(macosx): elif defined(macosx):
{.pragma: mylib, dynlib: "libffi.dylib".} {.pragma: mylib, dynlib: "libffi.dylib".}
else: else:
{.pragma: mylib, dynlib: "libffi.so".} {.pragma: mylib, dynlib: "libffi.so(.7|)".}
type type
Arg* = int Arg* = int
@ -78,7 +80,7 @@ type
size*: int size*: int
alignment*: uint16 alignment*: uint16
typ*: uint16 typ*: uint16
elements*: ptr ptr Type elements*: ptr UncheckedArray[ptr Type]
{.deprecated: [TType: Type].} {.deprecated: [TType: Type].}
var var
@ -94,7 +96,7 @@ var
type_float* {.importc: "ffi_type_float", mylib.}: Type type_float* {.importc: "ffi_type_float", mylib.}: Type
type_double* {.importc: "ffi_type_double", mylib.}: Type type_double* {.importc: "ffi_type_double", mylib.}: Type
type_pointer* {.importc: "ffi_type_pointer", mylib.}: Type type_pointer* {.importc: "ffi_type_pointer", mylib.}: Type
type_longdouble* {.importc: "ffi_type_longdouble", mylib.}: Type type_longdouble* {.importc: "ffi_type_double", mylib.}: Type
type type
Status* {.size: sizeof(cint).} = enum Status* {.size: sizeof(cint).} = enum
@ -140,5 +142,32 @@ proc prep_cif*(cif: var TCif; abi: TABI; nargs: cuint; rtype: ptr Type;
proc call*(cif: var TCif; fn, rvalue: pointer; proc call*(cif: var TCif; fn, rvalue: pointer;
avalue: ArgList) {.cdecl, importc: "ffi_call", mylib.} 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 # Useful for eliminating compiler warnings
##define FFI_FN(f) ((void (*)(void))f) ##define FFI_FN(f) ((void (*)(void))f)
when defined(nimHasStyleChecks):
{.pop.} # {.push styleChecks: off.}

View file

@ -1,11 +1,11 @@
# Package # Package
version = "1.0.1" version = "1.0.5"
author = "Andreas Rumpf" author = "Andreas Rumpf"
description = "libffi wrapper for Nim." description = "libffi wrapper for Nim."
license = "MIT" license = "MIT"
when defined(windows): when defined(windows):
installExt = @["nim", "c", "h", "s"] installExt = @["nim", "c", "h", "s"]
# Dependencies # Dependencies
requires "nim >= 0.10.0" requires "nim >= 0.10.0"