... | ... | @@ -17,27 +17,44 @@ qsort_b(void *base, size_t nel, size_t width, int (^compar)(const void *, const |
|
|
In C, we might use this function as described in Apple's introduction to blocks: [ Using a Block Directly](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks/Articles/bxGettingStarted.html#//apple_ref/doc/uid/TP40007502-CH7-SW2). We would like to be able to do the same in Haskell by declaring:
|
|
|
|
|
|
```wiki
|
|
|
foreign import ccall qsort_b "stdlib.h" :: Ptr a -> CSize -> CSize -> (Ptr a -> Ptr a -> Int) -> IO ()
|
|
|
foreign import ccall "stdlib.h" qsort_b
|
|
|
:: Ptr (StablePtr a) -- pointer to array of stable Haskell values
|
|
|
-> CSize -- size of the array
|
|
|
-> CSize -- size of a stable pointer to Haskell
|
|
|
-> (Ptr (StablePtr a) -> Ptr (StablePtr a) -> IO Int) -- comparison function
|
|
|
-> IO ()
|
|
|
|
|
|
myCharacters = ["TomJohn", "George", "Charles Condomine"]
|
|
|
```
|
|
|
|
|
|
|
|
|
and then executing
|
|
|
Note that the arguments to the comparison function are pointers to the array elements that need to be compared. Each of these array elements is, in turn, a stable pointer to a Haskell thunk.
|
|
|
|
|
|
```wiki
|
|
|
do
|
|
|
-- convert a list of strings into a C array of stable pointers to those strings in the Haskell heap
|
|
|
myCharactersArray <- newArray $ mapM newStablePtr myCharacters
|
|
|
|
|
|
-- get the size in bytes of a stable pointer to a Haskell string
|
|
|
let elemSize = fromInteger $ sizeof (undefined :: StablePtr String)
|
|
|
|
|
|
-- invoke C land 'qsort_b' with a Haskell comparison function passed as a block object; mutates 'myCharactersArray'
|
|
|
qsort_b myCharactersArray (length myCharacters) elemSize (\l r -> fromOrdering (l `compare` r))
|
|
|
When then use the C function from Haskell as follows:
|
|
|
|
|
|
-- turn the array of Haskell strings back into a list of strings
|
|
|
mySortedCharacters <- mapM deRefStablePtr myCharactersArray
|
|
|
```wiki
|
|
|
do { -- convert a list of strings into a C array of stable pointers to those strings in the Haskell heap
|
|
|
; ptrs <- mapM newStablePtr myCharacters
|
|
|
; sortedPtrs <- withArray ptrs $ \myCharactersArray -> do
|
|
|
{
|
|
|
-- get the size in bytes of a stable pointer to a Haskell string
|
|
|
; let elemSize = fromIntegral $ sizeOf (undefined :: StablePtr String)
|
|
|
|
|
|
-- invoke C land 'qsort_b' with a Haskell comparison function passed as a block object; mutates 'myCharactersArray'
|
|
|
; qsort_b myCharactersArray (length myCharacters) elemSize
|
|
|
(\l r -> do { l <- deRefStablePtr =<< peek lPtr
|
|
|
; r <- deRefStablePtr =<< peek rPtr
|
|
|
; return $ fromOrdering (l `compare` r)
|
|
|
})
|
|
|
|
|
|
-- obtain the sorted list of stable pointers from the sorted array
|
|
|
; peekArray (length ptrs) myCharactersArray
|
|
|
}
|
|
|
|
|
|
-- turn the array of Haskell strings back into a list of strings
|
|
|
; mySortedCharacters <- mapM deRefStablePtr sortedPtrs
|
|
|
}
|
|
|
```
|
|
|
|
|
|
|
... | ... | |