libffi
A binding to libffi
http://haskell.org/haskellwiki/Library/libffi
LTS Haskell 23.1: | 0.2.1 |
Stackage Nightly 2024-12-27: | 0.2.1 |
Latest on Hackage: | 0.2.1 |
libffi-0.2.1@sha256:72b41cefb799f3d3509c6cec8ecbf5023cf442c53a601aaaacee5872c722908b,2745
Module documentation for 0.2.1
libffi
A binding to libffi
, allowing C functions of types only known at runtime to be called from Haskell.
Notes on GHC’s bundling of libffi
This library makes a somewhat unusual choice: by default, it does not
explicitly declare a dependency against the libffi
C library. This is because
most binary distributions of GHC—that is, GHCs configured without the
--with-system-libffi
option—bundle their own copies of libffi
. One of these
copies is statically linked, and another of these copies is dynamically linked.
Moreover, whenever GHC compiles an executable, it will always pass the
necessary flags to link against its static copy of libffi
, as the GHC runtime
system depends on it.
When GHC bundles its own copies of libffi
, if you were to declare, say, an
extra-libraries: ffi
dependency, then it would not behave in the way that you
would expect. This is because:
-
The linker flags to link against GHC’s static copy of
libffi
always come first in the final linking step when compiling an executable. As a result, declaring anextra-libraries: ffi
dependency won’t make much of a difference, since GHC will always statically link against its own copy oflibffi
anyway due to the order of linker flags. -
Moreover, declaring an
extra-libraries: ffi
dependency can have the unfortunate side effect of declaring an unused dynamic dependency againstlibffi
. Even worse is the fact that the version of dynamically linkedlibffi
that comes with your operating system may differ from the version of dynamically linkedlibffi
that GHC bundles. When the version numbers differ, this can lead to the compiled executable failing at runtime with mysterious errors such as:error while loading shared libraries: libffi.so.7: cannot open shared object file: No such file or directory
For more information on this point, see GHC#15397.
Observation (2) means that when GHC is configured with --with-system-libffi
,
it is inherently fragile to use extra-libraries: ffi
. This is an unfortunate
situation, but there is not much that one can do about this short of fixing
GHC#15397 upstream. A workaround would be to configure GHC with
--with-system-libffi
, but practically speaking, the vast majority of GHC
binary distributions do not configure this way. This includes all versions of
GHC that ghcup
distributes, so unless we want to exclude most GHC users, we
need some kind of workaround for this issue.
Our workaround is to rely on observation (1). That is, because GHC always
passes flags to the linker to link against its own static copy of libffi
, we
can always assume that GHC will handle the libffi
dependency for us. As a
result, the default behavior for this library is to enable the
+ghc-bundled-libffi
flag, which means that the library will not declare an
external dependency on libffi
at all. This is rather unusual, but then again,
GHC bundling its own copies of libffi
is also unusual. (To our knowledge,
this is the only C library that GHC bundles in this fashion.)
We have tested out +ghc-bundled-libffi
on Windows, macOS, and Linux, and it
works as expected. If you encounter any linking oddities with
+ghc-bundled-libffi
, please file an issue.
It is worth re-emphasizing that +ghc-bundled-libffi
will only work if you are
using a binary distribution of GHC that was not configured with the
--with-system-libffi
option. If you are using such a GHC, then you will
need to use -ghc-bundle-libffi
(note the minus sign) to disable the flag and
link against your operating system’s copy of libffi
. Unfortunately, cabal
does not provide a way to detect whether GHC was configured with
--with-system-libffi
or not, so the burden is on users to enable or disable
ghc-bundle-libffi
as appropriate.
Changes
0.2.1 [2022.09.24]
- Add
sizeAndAlignmentOfCType
toForeign.LibFFI.Base
, which can be used to retrieve the size and alignment of aCType
.
0.2 [2022.08.11]
-
The
libffi
library now usesbracket
internally and should now be exception-safe. -
There is a now a
ghc-bundled-libffi
cabal
flag that makes this library statically link against GHC’s bundled copy oflibffi
rather than attempt to link against the systemlibffi
. On the vast majority of GHCs, this is the most reasonable option, as linking against the systemlibffi
is inherently fragile. As a result,+ghc-bundled-libffi
is now the defalut setting. See theREADME
for more discussion on this point. -
The definition of
Arg
has changed:-newtype Arg = Arg { unArg :: IO (Ptr CType, Ptr CValue, IO ()) } +newtype Arg = Arg { unArg :: forall a. (Ptr CType -> Ptr CValue -> IO a) -> IO a }
-
The definition of
RetType
has changed:-data RetType a = RetType (Ptr CType) ((Ptr CValue -> IO ()) -> IO a) +newtype RetType a = RetType { unRetType :: (Ptr CType -> Ptr CValue -> IO ()) -> IO a }
0.1 [2009.03.17]
- Initial release.