Talk:Foreign function interface
|WikiProject Computing||(Rated Start-class)|
|WikiProject Computer science||(Rated Start-class, Low-importance)|
|Sources for development of this article may be located at|
Code example, with copyright question mark
I wrote the following code example, based on an O'Reilly book. The only part from the book is the code itself; the prose is all mine. Unfortunately the book is "all rights reserved" so I'm not sure that using it would be legal. I don't suppose a claim of fair use would be acceptable? If not (or it wouldn't be considered fair use anyway) I'll see if I can get permission. Hairy Dude (talk) 07:25, 25 April 2009 (UTC)
Haskell's FFI provides a raw "foreign import" mechanism, which, given a symbol in a particular header file and a name and appropriate type signature, will bring a Haskell function of that name and type into scope and bind the C function to it. By "appropriate type" we mean that the types of the arguments of the C function and its return type each have an associated Haskell type, which is often a black box. Part of the function of the FFI is to provide a way of marshalling Haskell data into the correct format for use by the C function, and marshalling the C data that it returns into a form that the Haskell code can use.
A further complication is that Haskell is a "pure" language: ordinary code does not permit side effects, whereas C is "impure": it allows unrestricted side effects. Haskell code that does have side effects is separated by having its type marked with "IO", which cannot usually be stripped off (to allow it would enable ostensibly "pure" code to have side effects). As a matter of fact, while it is rare for a C function to have no side effects at all, in many cases the only side effects are allocation of memory for the return value and modification of buffers which are passed in as arguments (so-called reentrant functions). These types of side effect can easily be encapsulated.
Finally, there is the issue of memory management: C usually explicitly allocates and deallocates memory using the pair
free(), whereas Haskell uses implicit allocation and garbage collection. If we are to use a data value returned by a C function in Haskell, we must arrange for it to be managed by the garbage collector and ensure that it gets disposed of in the proper way — by calling
free() — or we will get a memory leak.
-- Import the function. -- Note the C-native types such as "CString" (*char) and "Ptr CInt" (*int). foreign import ccall unsafe "pcre.h pcre_compile" c_pcre_compile :: CString -> PCREOption -> Ptr CString -> Ptr CInt -> Ptr Word8 -> IO (Ptr PCRE) ... -- The wrapper. Note the Haskell-native types ByteString and String. compile :: ByteString -> [PCREOption] -> Either String Regex compile str flags = unsafePerformIO $ useAsCString str $ pattern -> do alloca $ \errptr -> do alloca $ \erroffset -> do pcre_ptr <- c_pcre_compile pattern (combineOptions flags) errptr erroffset nullPtr if pcre_ptr == nullPtr then do err <- peekCString =<< peek errptr return (Left err) else do reg <- newForeignPtr finalizerFree pcre_ptr return (Right (Regex reg str))
The first two lines import the C function in question as
c_pcre_compile. The rest of the code is a wrapper
compile which provides a native Haskell interface for the function: it takes a ByteString instead of a CString (i.e. a null-terminated character array), and it reports errors through its return type, rather than by returning an invalid value (like a null pointer) and causing the side-effect of writing a string to a buffer, as the C function does.
Marshalling is performed in the following way:
useAsCStringconverts the input ByteString into a C string.
peekdereferences the pointer to get at the C string it points to (the error message), which
peekCStringturns into a String.
newForeignPtrcreates a new managed pointer, essentially registering the pointer with the garbage collector so it reclaims the memory used by the data when it goes out of scope. This includes specifying the finalizer, which is a function to call on the pointer when it gets garbage-collected, to make sure it is disposed of properly. In this case,
finalizerFreewill call the C function
- The data constructor
Regexencapsulates the managed pointer to the opaque type PCRE, representing the C type of the compiled regular expression, along with the string that it was compiled from, as a Haskell type.
The function also requires two temporary buffers, which are allocated using
alloca. Normally this would need to be told how much memory to allocate, but Haskell's type inference can provide this information automatically. Finally, after all the side-effects have been encapsulated, the otherwise dangerous function
unsafePerformIO strips the "IO" marker and allows the function to be used in a pure context.
the template looks horrible in source code, clutters things. This kind of things must be automated to be useful and maintainable. Suggestion: remove from article. --Sigmundur (talk) 13:51, 29 September 2010 (UTC)
An FFI or a FFI
Hello fellow Wikipedians,
I have just modified one external link on Foreign function interface. Please take a moment to review my edit. If you have any questions, or need the bot to ignore the links, or the page altogether, please visit this simple FaQ for additional information. I made the following changes:
- Added archive https://web.archive.org/web/20120728074805/http://java.sun.com/docs/books/jni/ to http://java.sun.com/docs/books/jni/
When you have finished reviewing my changes, you may follow the instructions on the template below to fix any issues with the URLs.
You may set the
|checked=, on this template, to true or failed to let other editors know you reviewed the change. If you find any errors, please use the tools below to fix them or call an editor by setting
|needhelp= to your help request.
- If you have discovered URLs which were erroneously considered dead by the bot, you can report them with this tool.
- If you found an error with any archives or the URLs themselves, you can fix them with this tool.
If you are unable to use these tools, you may set
|needhelp=<your help request> on this template to request help from an experienced user. Please include details about your problem, to help other editors.
Foreign function call
Foreign function call links here. I'm wondering whether or not it makes sense to move this page to that title, and generalize to include such things as RPC. — Preceding unsigned comment added by 18.104.22.168 (talk) 05:59, 13 January 2017 (UTC)