Jump to content

Talk:Foreign function interface

Page contents not supported in other languages.
From Wikipedia, the free encyclopedia
[edit]

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)[reply]


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 malloc() and 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.

In the following example (from the book Real World Haskell[1]), the function pcre_compile, written in C as part of the PCRE library, is to be imported into Haskell.

-- 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:

  • useAsCString converts the input ByteString into a C string.
  • peek dereferences the pointer to get at the C string it points to (the error message), which peekCString turns into a String.
  • newForeignPtr creates 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, finalizerFree will call the C function free().
  • The data constructor Regex encapsulates 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.

  1. ^ O'Sullivan, Bryan; Goerzen, John; Stewart, Donald (2008). Real World Haskell. O'Reilly. ISBN 0596514980. Retrieved 25 April 2009.

Abbreviation markings

[edit]

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)[reply]

An FFI or a FFI

[edit]

The article is using both inconsistently. — Preceding unsigned comment added by SimEdw (talkcontribs) 14:22, 8 March 2012 (UTC)[reply]

In The Rust Book, "An FFI" is used. — Preceding unsigned comment added by Geophertz (talkcontribs) 17:31, 8 June 2019 (UTC)[reply]

[edit]

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:

When you have finished reviewing my changes, you may follow the instructions on the template below to fix any issues with the URLs.

This message was posted before February 2018. After February 2018, "External links modified" talk page sections are no longer generated or monitored by InternetArchiveBot. No special action is required regarding these talk page notices, other than regular verification using the archive tool instructions below. Editors have permission to delete these "External links modified" talk page sections if they want to de-clutter talk pages, but see the RfC before doing mass systematic removals. This message is updated dynamically through the template {{source check}} (last update: 5 June 2024).

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

Cheers.—InternetArchiveBot (Report bug) 20:05, 2 January 2017 (UTC)[reply]

Foreign function call

[edit]

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 75.139.254.117 (talk) 05:59, 13 January 2017 (UTC)[reply]

vala also has an ffi for c

[edit]

I believe vala also has an ffi for c.

Maybe somebody who knows enough about vala could add a sentence to the long list of languages with ffis to c here?

Son of eugene (talk) 03:23, 17 April 2019 (UTC)[reply]

Origin of the term "Foreign Function Interface"

[edit]

The article claims that the name FFI originates with Common Lisp. This claim was present in the very first version of the article from 2006 (https://wiki.riteme.site/w/index.php?title=Foreign_function_interface&oldid=37186059), but without any source or citation. A citation was added in 2015 (https://wiki.riteme.site/w/index.php?title=Foreign_function_interface&oldid=667577477), but that citation is incorrect. Specifically, the article says:

The term comes from the specification for Common Lisp, which explicitly refers to the language features for inter-language calls as such

Providing a source for this claim means you would need to cite either the Common Lisp specification or a publication referring to the Common Lisp spec. However, the citation given refers to the CFFI user manual at https://cffi.common-lisp.dev/manual/cffi-manual.html. CFFI is just a library for Common Lisp; it is not part of the language specification or "official" in any way. Also, CFFI was first published in 2005, long after the term FFI had been used in e.g. Haskell (https://www.haskell.org/definition/ffi/, 2000).

Thus the citation should be removed as irrelevant (and be replaced by something better, but see below).

Second, I can't find any reference to "FFI" or "foreign function" in the Common Lisp HyperSpec, which is not quite the ANSI standard from 1994 (ANSI/X3.226), but the closest thing we have on the open internet. The latest ANSI draft does not list "FFI" or "foreign" in its index or glossary, either. That, and the subsequent creation of libraries like CFFI (2005) and UFFI (2002), lead me to believe that the term does not come from Common Lisp after all. The first document or project using the term "FFI" that I can find is libffi (1996).

Does anyone know where the name comes from? 84.149.130.33 (talk) 10:48, 16 December 2022 (UTC)[reply]