Author : Julian Fleischer
Changes : 2013-05-28 First version
2013-06-01 Added *.cpphs
2013-06-03 +Roadmap, +Coding Guidelines, few quirks fixed
What you should know up front
=============================
WORKSPACE REQUIREMENTS
----------------------
This library has proudly been built using a Terminal and VIM,
which is all you need to start developing.
( well, the Haskell Platform and a JDK would be necessary too,
but hey, you surely figured /that/. )
USE OF PREPROCESSORS
--------------------
In order to reduce code duplication and enhance both the readability
and the ease of writing code, two preprocessors are used throughout
the package. They are defined in `Setup.hs'. Thus this package
requires to be built with cabal.
The following file types are specially treated:
*.tpl
Used for Foreign.Java.JNI.{Safe|Unsafe}. Both of these files
are nearly identical to each other, except for having "safe"
or "unsafe" along foreign imports. A *.tpl file contains a
relative path to a template file and a list of key/value pairs.
The key/value pairs are replaced in the template and a regular
Haskell file is generated.
Example.tpl:
> ("example-template.hs", [("SAFETY"), ("safe")])
example-template.hs
> main = "This is the %SAFETY% version."
yields Example.hs:
> main = "This is the safe version."
The preprocessor is defined in `Setup.hs'
in the function `transformTpl'.
*.hss
Haskell with syntactic sugar for multiline strings and
string interpolation. It allows for the following:
> aRatherComplexString :: String -> [String] -> Int -> String
> aRatherComplexString x y z = """
> The arguments are
> x = #{x}
> y = #{unlines y}
> z = #{show z}
> """
The preprocessor is defined in `Setup.hs'
in the function `transformHss'.
HSS files are used wherever large amounts of dull string
processing are required, such as when generating code.
*.cpphs
Haskell with cpp (c preprocessor) directives. This is mostly the
same as using the CPP extension (-XCPP). The CPPHS preprocessor
uses the implementation from the hackage package `cpphs').
The cpphs preprocessor allows for modern ansi features such as
stringification and token pasting (the CPP extension runs cpp in
traditional mode, which does not include modern ansi features).
cpphs is used through out this project to reduce the amount
or repetetive code and is considered a simpler alternative to
Template Haskell. -XCPP instead of cpphs is used wherever a
value from the outside (-D... -> #ifdef) is needed.
-> http://projects.haskell.org/cpphs/
-> http://hackage.haskell.org/package/cpphs
WHAT GOES WHERE
---------------
src/ffijni.h src/foreign.c
Hand-written glue code for interfacing the FFI with the JNI.
src/Foreign/Java/JNI/*.{tpl|hs}
These files contain the Core JNI binding.
src/Foreign/Java.hs
This file contains the medium level API.
src/Foreign/Java/Bindings.hss src/Foreign/Java/Bindings/...
These files contain functions for reflecting
Java classes and Haskell modules, and generating
high level glue code.
src/Foreign/Java/Bindings/Support.cpphs
This file contains more-or-less private definitions
that are used by the generated Haskell modules only.
The module is public (that is "not hidden") so that
bindings can live in a package other than java-bridge.
It should however be considered an internal package.
src/Foreign/Java/{all other files}
Utilities (Foreign.Java.{IO / Maybe / Print / ...})
examples/
Examples. Don't forget to add files and executables in
java-bridge.cabal when adding examples or anything.
Most examples are not that impressive, but offer simple
tutorials of various aspects of the API of the java-bridge.
hs2j/ j2hs/
The respective tools. Mostly boring code to orchestrate the
interplay of functions from Foreign.Java.Bindings.*
GetProperty.java
This file is used for setup on Linux/Unix to retrieve system
properties form the JVM.
Makefile
Does little more than calling cabal. Use as inspiration on how to
use cabal for building (which is really easy).
Setup.hs
The project uses a Custom build type, which is defined in here.
Preprocessors and functions for finding libjvm live here.
CODING GUIDELINES
-----------------
Please try to stick to a maximum line width of 80 characters, 72 if
possible. Sometimes that limit is exceeded, however 100 characters
should really never be reached. Thus:
Soft constraint:
72 characters per line.
Hard constraint:
80 characters per line.
Do-not-cross-never-ever:
100 characters.
When defining methods that perform case analysis, use a case construct
rather than multiple method definitions:
GOOD:
> function x = case x of
> C1 -> ...
> C2 -> ...
BAD:
> function C1 = ...
> function C2 = ...
This greatly enhances maintainability `plus` it safes a few keystrokes.
DISTRIBUTION
------------
Due to the use of preprocessors the regular `cabal sdist' will fail.
This seems to be a known bug. The workaround is to manually invoke the
build script:
$ ./dist/setup/setup sdist
( you need to have invoked `cabal configure' first,
otherwise `setup' will not have been built yet. )
-or-
$ runhaskell Setup.hs sdist
( note that on some machines this fails badly with a GHCi runtime error
(issues with linking), so it's probably better to compile and run
`setup', as shown above. )
The matter has been discussed on stackoverflow:
-> Haskell - Packaging cabal package with custom preprocessors
http://stackoverflow.com/q/16256987/471478
Roadmap
=======
This section describes known issues that will be worked on.
OS X (GUI) QUIRKS
-----------------
See also:
-> Java JNI: Creating a Swing Window using JNI from C
http://stackoverflow.com/q/14661249/471478
-> Linking a library with GHC and Cabal in Mac OS X
http://stackoverflow.com/q/16383988/471478
Starting points:
Foreign.Java
-> runJavaGui and runJavaGui'
Foreign.Java.JNI.{Safe/Unsafe}
-> runCocoaMain :: IO ()
src/ffijni.c
-> void runCocoaMain()
CLASS CACHE (ENHANCEMENT)
-------------------------
Would it speed things up if class references were cached in the Java
monad? Currently every invocation of a method (especially in the high
level bindings) does a new lookup.
The medium level bindings are not affected.
OVERHAUL *.hss PREPROCESSOR
---------------------------
The current implementation is uggly hackery. Overhaul and maybe release
as a package in its own right.
JAVADOC -> HADDOCK
------------------
It would be really great if the generated haddock documentation for the
high level bindings would contain the javadoc of the translated classes
and methods.