Skip to content
Manuel M T Chakravarty edited this page Apr 12, 2014 · 6 revisions

Marshalling

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.)

Automatic marshalling

Types for which we want to provide automatic marshalling:

  • Everything in Foreign.C.Types
  • Between Haskell String and Objective-C NSString (and char * and wchar_t* for plain C)
    • On OS X, WCString is UTF-32le. Convert Strings with Foreign.C.String to wchar_t* and then produce an NSString with initWithBytes:length:encoding: and NSUTF32LittleEndianStringEncoding.
    • Also support Data.Text: convert to Ptr Word16 with Data.Text.Foreign and then init an NSString with initWithBytes:length:encoding: using NSUTF16LittleEndianStringEncoding.
  • Plist types — see support by ObjectiveHaskell

System-dependent types

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.

Structure of the bridging code for inline foreign expressions

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.

Structure of the bridging code for Haskell functions used in foreign code

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.