9.0
top
← prev up next →

Dynamic FFIπŸ”— i

This module produces automatic ABI-native FFI bindings to C libraries.
Dynamic FFI is a native Racket extension which embeds clang/llvm to parse out declarations from C headers and dynamically build FFI objects with correct type/size information. This library is currently only available for GNU/Linux and macOS, but should be easily portable to other operating systems. If you are experienced with building clang/llvm plugins on other OSes and would like to contribute, please contact the author.
This module uses native extensions to Racket’s C runtime, and is not currently compatible with Racket-on-Chez. Support for Racket-on-Chez is planned for the future.

1Warning: Read this Section Before UseπŸ”— i

Like Racket’s built-in ffi/unsafe module, this library allows Racket to use C functions and data structures that are not memory-managed by Racket. Racket cannot provide safety guarantees by default for FFI objects created using this library. Users of this library will be required to self-enforce memory management in C and/or manually expose FFI objects to Racket’s garbage collector. Extra care should be taken to ensure that C functions bound via this library or Racket’s built-in FFI do not contain errors like buffer overflows, which could corrupt the runtime, cause undefined behavior, and prevent Racket from providing useful error messages.

Users of this library should be extremely cautious. The library makes it easier to call C functions from Racket, but does not make it safer.

Finally:

Passing unsanitized user-input to any function in this library is horribly dangerous. You should never do it under any circumstance.

2DependenciesπŸ”— i

Dynamic FFI requires clang and llvm headers and libraries to work. Clang versions 6 and 7 are both known to work with Dynamic FFI. This library does not bundle clang or llvm.

To install a clang toolchain on Fedora:

sudodnfinstall"@developmenttools"racketllvm-develclang-devel

To install a clang toolchain on Ubuntu:

sudoapt-getinstall"build-essential"racketllvm-devlibclang-devclang

To install a clang toolchain on macOS (assuming that Homebrew is installed), run brewinstallllvm, then follow the instructions emitted by Homebrew to setup paths.

During the raco package install, Dynamic FFI will compile itself and link with the system clang libraries. Dependencies should be installed before the raco installation, or else the library will defer building itself, and will complain about missing dependencies when you try to use it. To finish the installation process, install the required dependencies and run the following command:

racosetup-p-Ddynamic-ffi

3Defining FFIsπŸ”— i

syntax

( define-dynamic-ffi idlibheader...)

Parses headers for syntax tree data and builds dynamic FFI bindings. The resulting id will be bound to a case-lambda function which takes the name of the C function as the first argument, and the C function parameters as the rest. If the defined id is called with no arguments, a hash-map of all symbols and FFI objects in the library is returned.

lib can be a relative library created using dynamic-ffi-lib , or a hard-coded path omitting the object file extension.

(require dynamic-ffi/unsafe)
(dynamic-ffi-lib "libc""6")
"/usr/include/stdio.h")
(libc'printf"hello world\n")

procedure

( dynamic-ffi-lib libversion...)
version:string?
Takes a library base name and shared object versions, and produces a list argument which can be used in place of a hard-coded system object file path. In the above define-dynamic-ffi example, Racket will search for libc.so.6 in the default system library paths.

syntax

( define-dynamic-ffi/cached idlibheader...)

lib : (or/c string? path? )
header : (or/c string? path? )
This form behaves the same way as define-dynamic-ffi , except it caches static FFI bindings so that they do not need to be recomputed in future program executions.

4Generating Static FFIsπŸ”— i

This library has the ability to generate static FFI files that can be used without the dependency on dynamic-ffi.

procedure

( generate-static-ffi ffi-name
file
lib-path
headers...)void?
ffi-name:(or/c string? symbol? )
file:(or/c string? path? )
headers:(or/c string? path? )
Generates a static FFI where identifiers corresponding to C function names are prefixed with ffi-name and bound to their associated FFI objects.

procedure

file
lib-path
headers...)void?
ffi-name:(or/c string? symbol? )
file:(or/c string? path? )
headers:(or/c string? path? )
Generates a static FFI whose interface is equivalent to the case-lambda function produced by define-dynamic-ffi .

5Inline FFIsπŸ”— i

This library allows users to write C functions inline, which will be compiled at runtime and provided as a dynamic FFI.

syntax

( define-inline-ffi namecode...[#:compilercompiler]
[#:compile-flagsflags])
code : string?
compiler : string?
flags : (or/c string? 'auto)
Define FFI bindings by writing inline C code. This form is designed for use with the at-reader. For security reasons define-dynamic-ffi only accepts C code as string literals.

intadd(intx,inty){
returnx+y;
}
}
(mylib' add34)

The form can be used without the at-reader as well.

"int add(int x, int y) {\n"
"return x + y;\n"
"}")
(mylib'add34)

Extra compile flags can be passed to define-inline-ffi , and the default compiler can be overridden.

(define-inline-ffi libm#:compile-flags"-lm"#:compiler"clang"
"#include <math.h>\n"
"double square_root(double x) {\n"
"return sqrt(x);\n"
"}")
(libm'square_root16)

6LimitationsπŸ”— i

This library is able to generate dynamic FFI bindings for a fairly large portion of the C language standard. Occasionally we find special declaration types that clang treats differently, which the library may not have support for yet. When such declarations are encountered, dynamic-ffi will emit error messages with details about the missing functionality. Please report any issues you find at the project issue tracker.

As a workaround in almost every case, define-inline-ffi can be used to write a wrapper around functions that dynamic-ffi is unable to parse.

7AcknowledgementsπŸ”— i

Special thanks to Jay McCarthy for suggesting this project idea, and for his advisership during its implementation.

top
← prev up next →

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /