-
Notifications
You must be signed in to change notification settings - Fork 29
Design
Currently, automatic marshalling is dependent on a Haskell type only. Ideally, it would be determined on the basis of a pair of Haskell and (Objective-)C type, as in C->Haskell, but we currently don't have sufficient type information for the inline C code. (In a subsequent revision, we may want to improve this.)
Types for which we want to provide automatic marshalling:
- Everything in
Foreign.C.Types
- Between Haskell
String
and Objective-CNSString
(andchar *
andwchar_t*
for plain C)- On OS X,
WCString
is UTF-32le. ConvertString
s withForeign.C.String
towchar_t*
and then produce anNSString
withinitWithBytes:length:encoding:
andNSUTF32LittleEndianStringEncoding
. - Also support
Data.Text
: convert toPtr Word16
withData.Text.Foreign
and then init an NSString withinitWithBytes:length:encoding:
usingNSUTF16LittleEndianStringEncoding
.
- On OS X,
- Plist types — see support by ObjectiveHaskell
Numeric types whose representation is system-dependent, such as Int
, are marshalled to the system-dependent type of the same name in C — i.e., we map Int
to int
. This is unsafe in so far as we may lose information when marshalling in either direction. However, it is better than mapping a given Haskell type to varying C types in dependence on the target architecture. If we did the latter, code that compiles on one platform might fail to compile on another.
To achieve a robust interface, always use types with a fixed representation, such as Int32
, or types that are guaranteed to be equivalent to known C types, such as Foreign.C.Types.CInt
.
For every occurrence of inline C code, we need to generate the following artefacts:
- A static C function that serves as a wrapper of the foreign code.
- A foreign import declaration for the wrapper in Haskell.
- This implies that we need to determine bridging or wrapper types that can be natively marshalled by Haskell's C FFI for every free variable of the inline C code (which will become an argument to the wrapper) and for the result of the inline C code (which will become the result of the wrapper).
- Haskell marshalling code from the type of every free variable of the inline C code to the Haskell type of the corresponding wrapper argument as well as Haskell marshalling code from the result of the wrapper to the type expected of the result of the inline C code.
- (Objective-)C marshalling code from the argument types of the wrapper to the types expected of the free variables by the inline C code as well as marshalling code from the result of the inline C code to the result type of the wrapper. The type expected and produced by the inline C code is currently inferred on the basis of the Haskell type of the free variables and the result type explicitly passed to the splicing function.
For every Haskell function (including CAFs) used in foreign code, we need to generate the following artefacts:
- A Haskell wrapper function encapsulating the Haskell-side marshalling of arguments coming in from a C call and marshalling of the Haskell result back to C land.
- A C function encapsulating the (Objective-)C-side marshalling of arguments used to call the Haskell wrapper and the marshalling of the C result.
- Haskell and (Objective-)C marshalling code much as for free variables and the result of inline expressions.