bindings-0.1: src/Bindings.hs
{-|
Modules under "Bindings" are supposed to be low level links to
non-Haskell packages, sharing a set of community driven guidelines on
procedures, goals and style. (Note that, until others get interested
in this work, \"community\" means just the author.) This is the
current set of guidelines:
* Code should be portable and easy to build.
* There should be a one-to-one relashionship between names in the
original library and its bindings. Also, the behavior of elements
should be what would be expected from the element of the original
library it represents.
* As a planed consequence of the former item, the reference
documentation for all modules should be the documentation available
for the original libraries. Documentation and comments to Haskell
binding code should be restricted to explain decisions that had to be
made to solve ambiguities or provide functionality that could not be
mapped to an exact Haskell equivalent.
* All foreign functions are declared @safe@. Also, they should
all result in a 'System.IO.IO', even when they are supposed to
be effect-free. This is both for consistency and security, since
otherwise it would be difficult to inspect all the code to check which
functions are actually guaranteed to be effect-free. Constant values,
however, may be represented by pure functions.
* Global variables whose values can be changed by a library user
are wrapped throw type 'Bindings.Utilities.GlobalVar'. When their
values can't be changed by the user, but still they can change as
the execution goes, they are wrapped throw functions returning an
'System.IO.IO'. (This last case, of course, may need helper functions
written in the foreign language.)
* Names in Haskell should match the corresponding names in original
libraries, prefixed with \'@_@\' when starting with an uppercase
letter, or with first letter uppercased when naming types. Exception
is made to prefixes used to emulate namespaces. In this case, prefixes
are stripped, and they are expected to be replaced by qualified
imports, e.g., a function named @somepkg_anyfun@ should be named just
@anyfun@ and may be used as @SomePkg.anyfun@. Also names for basic
types, like fixed size integers or pointers, should be consistent with
style used in "Foreign.C.Types".
* Module "Bindings.Utilities" has an enumeration of function types
('Bindings.Utilities.CB0001', 'Bindings.Utilities.CB0002' etc.) which are
supposed to be used (and incremented when necessary) to type callback
functions. Foreign functions parameters expecting callback pointers
should be typed as pointers to function types in that enumeration;
except when those callbacks are just data destructors, when they
should be typed as 'Foreign.ForeignPtr.FinalizerPtr'.
* Users can suggest tests using "Test.HUnit" or "Test.QuickCheck"
using the bug tracking system. Test shown to be valid will be included
with a test program included in this package.
The names for files and directories in the source pack follow the
usual convention of mapping module names to file names. A similar
convention is followed by C files that support those modules. There
are also a few special directories:
[@packageCode@] This directory contains the source code for the
foreign libraries. When appropriate, steps necessary to build a library
will be listed in a file here.
[@packageCode\/include@] Support files needed by this package to
properly wrapp libraries (like @C@ include files) are placed here.
They should be simplified as much as possible to contain only the
required information.
[@traduttoreTraditore@] Here example code for wrapped libraries can be
found. However, only Haskell translations for code already available
for those libraries in \"official\" places (like the homepage for the
library, or inside its source code distribution) are allowed. Best
effort should be made to keep those translations faithfull to the
original code, so that readers could follow then side by side.
-}
module Bindings where
import Foreign
import Foreign.C
import Control.Monad
import Control.Exception
data License = ApacheLicenseV2 | BSD3 | GPL | GPLv3 | LGPL | LGPLv3
| MIT | MPL | CDDL | CPL | EPL | ArtisticLicenseV2 | OSLv3 | Zlib |
AfferoGNUv3 | SimPLv2 | Proprietary | Private
data Package = Sqlite3 deriving (Eq, Show)
-- | Given the license you have choosen for your
-- work, this function tells you which libraries
-- in this package you're allowed to use.
whatCanBeUsedWithThisLicense :: License -> [Package]
whatCanBeUsedWithThisLicense _ = [Sqlite3]
-- | When libraries require an initialization call to
-- be made at startup, the related functions are not
-- wrapped. Instead, we use 'initialize' as a common
-- initialization point for all libraries. You can
-- use 'initialize' at the beginning of 'main' and
-- 'shutdown' at the end. Repeated calls to 'initialize'
-- cause no harm.
initialize :: [Package] -> IO ()
initialize p = do
when (Sqlite3 `elem` p) $ do
status <- bindings_init_sqlite3
when (status == 0) $ (throwIO $ AssertionFailed "Failed \
\initialization of libraries in package 'bindings'.") >> return ()
initializeAll = initialize [Sqlite3]
shutdown = bindings_shutdown
foreign import ccall "bindings_init_sqlite3" bindings_init_sqlite3
:: IO CInt
foreign import ccall "bindings_shutdown" bindings_shutdown
:: IO ()