# Portable Foreign Function Interface for R7RS schemes Foreign function interface that is supported on multiple R7RS Sceheme implementations. Pull requests to fix bugs and add more tests are welcome. Got a [bug](https://codeberg.org/r7rs-pffi/pffi/projects/9101)? Got a [feature suggestion](https://codeberg.org/r7rs-pffi/pffi/projects/9102)? Got a [question](https://codeberg.org/r7rs-pffi/pffi/projects/9575)? ## Goals - Support only R7RS implementations - Needs to have cond-expand and library support atleast (propably much more) - Same interface on all implementations - Some things that are procedures on one implementation are macros on other, but they must behave the same ## Non goals - To support all R7RS implementations - To have every possible FFI feature - Compiling of C code at any point - That is no stubs, no C code generated by the library and so on For bugs you can use the [Bugs](https://codeberg.org/r7rs-pffi/pffi/projects/9101) ## All tests (there is not that many yet) pass - [Sagittarius](https://bitbucket.org/ktakashi/sagittarius-scheme/wiki/Home) - [Guile](https://www.gnu.org/software/guile/) - [Kawa](https://www.gnu.org/software/kawa/index.html) - Needs atleast java 21 - Needs jvm flags - java --add-exports java.base/jdk.internal.foreign.abi=ALL-UNNAMED --add-exports java.base/jdk.internal.foreign.layout=ALL-UNNAMED --add-exports java.base/jdk.internal.foreign=ALL-UNNAMED --enable-native-access=ALL-UNNAMED --enable-preview -jar kawa.jar FILENAME.scm - [Racket](https://racket-lang.org/) - [Chicken](https://www.call-cc.org/) ## Not all tests pass - [STKlos](https://stklos.net/) - [Cyclone](https://justinethier.github.io/cyclone/) - [Gambit](https://gambitscheme.org) ## Support waiting for the implementation - [LIPS](https://lips.js.org/) - Waiting for implementation to have cond-expand and library support - Will only work on nodejs ## Not supported - [Chibi](https://synthcode.com/scheme/chibi) - FFI requires C code - [MIT-Scheme](https://www.gnu.org/software/mit-scheme/) - FF requires C code - [tr7](https://gitlab.com/jobol/tr7) - FFI requires C code - [Gauche](https://practical-scheme.net/gauche/) - FFI requires C code ## Hacking main.sld is the real main which is copied to main.scm ## Documentation On some implementations these are procedures, on some macros. The arguments are in form - NAME - TYPE The return value is in form - TYPE ### Types Types are given as symbols, for example 'int8 or 'pointer. - int8 - uint8 - int16 - uint16 - int32 - uint32 - int64 - uint64 - char - unsigned-char - short - unsigned-short - int - unsigned-int - long - unsigned-long - float - double - string - pointer ### Procedures or macros #### pffi-shared-object-auto-load Arguments: - headers - (list string ...) - C headers of the library - For example (list "curl/curl.h") - object-name - symbol - The name of the dynamic library file you want to load - Without the "lib" in front of it - Without the ".so" or ".dll" at the end - addition-versions - (list string...) - For example (list ".0" ".1") - addition-paths - (list string...) - Any additional paths you want to search for the library - For example (list "./mylibs") Returns: - object - Shared object, the type depends on the implementation #### pffi-shared-object-load It is recommended to use the pffi-shared-object-auto-load instead of this directly. Arguments: - headers - (list string ...) - Headers that need to be included - Example (list "curl/curl.h") - path - string - The full path to the shared object you want to load, including any "lib" infront and .so/.dll at the end - Example "libcurl.so" Returns: - object - Shared object, the type depends on the implementation #### pffi-define Defines new foreign procedure. Arguments: - scheme-name - The name of the procedure used on scheme side - shared-object - object - The shared object - Use pffi-shared-object-auto-load or pffi-shared-object-load to get this - c-name - symbol - The name of the C function - return-type - symbol - The return type of the C function - arguments-types - (list symbol ...) - The C function argument types ### pffi-size-of Get the size of type. Arguments: - type - symbol - The type you want the size of Returns: - number - The size of the given type ### pffi-pointer-allocate Allocates a pointer of given size. Arguments: - size - number - The size of the pointer you want to allocate Returns: - object - A pointer of given size ### pffi-pointer-null Create a null pointer. Returns: - object - Null pointer ### pffi-string->pointer Arguments: - string-content - string - The string you want to transform into pointer Returns: - object - Pointer of the given string ### pffi-pointer->string Arguments: - pointer - object - The pointer you want to transform to string Returns: - string - String from the given pointer ### pffi-pointer-free Arguments: - pointer - object - The pointer you want to free ### pffi-pointer? Arguments: - object - object - The object you want to check wether it is a pointer or not Returns: - boolean - Returns true if given object is pointer, otherwise false ### pffi-pointer-set! Arguments: - pointer - object - The pointer you want to modify - type - symbol - The type of value that will be put into the pointer - offset -number - The location of the value inside the pointer - For example: (+ (pffi-size-of 'int) (pffi-size-of 'pointer)) or 0 - value - object - The value to be placed into the object ### pffi-pointer-get Arguments: - pointer - object - The pointer you want to get the value from - type - symbol - The type of value you want to get - For example: 'int - offset - number - The location of the value inside the pointer - For example: (+ (pffi-size-of 'int) (pffi-size-of 'pointer)) or 0 Returns: - object - The value in the poiner in the given offset as given type ### pffi-pointer-deref Arguments: - pointer - The pointer to dereference Returns: - object - Whatever the pointer holds