Dobrze (twoja lokalna pora dnia), wszyscy.Testowanie kodu FFI (z "importem zagranicznym") z GHCi
Przeszedłem przez Real World Haskell's chapter w interfejsie funkcji zagranicznej, i zrobiłem kilka następnych odczytów here. Eksperymentuję teraz z wiązaniem funkcji C i , a ja chciałbym wyjaśnienia niektórych rzeczy.
co następuje dość jasne:
foreign import ccall unsafe "math.h sin" c_sin :: CDouble -> CDouble
mogę załadować to i kod, który używa go w ghci, i wszystko jest w porządku. To nawet ładuje wbudowane ghci w trybie Haskella emacsa. Uważam to za świetne do testowania. math
to biblioteka systemowa, więc jest to proste.
Teraz przykład z Real World Haskell:
foreign import ccall unsafe "pcre.h pcre_compile" c_pcre_compile :: ...
zostawiłem resztę podpisu funkcji celowo. Teraz nie mogę załadować tego w trybie Haskella . Wszystkie przykłady widziałem powiedzieć to musi być zrobione:
ghci -lpcre
Co zrobić i uzyskać natychmiastowe potwierdzenie, że rzeczy są ładowane poprawnie:
GHCi, version 7.6.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading object (dynamic) /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../lib/libpcre.so ... done
final link ... done
mogę następnie załadować moje wiązania kod i przetestować z dala, ale ...
_Question 1_ Czy mogę załadować biblioteki niesystemowe z ghci, jak pcre? To by pozwoliło mi przetestować w emacs.
Przeprowadzka. Rzeczy stają się bardziej skomplikowane, gdy próbuję napisać powiązania z moim kodem z własnym kodem.
foreign import ccall unsafe "myprint.h myprint" c_myprint :: CString -> IO()
Co prawda dość bezcelowa funkcja. Zajmuje ByteString z Haskell i Drukuje C. Oto prosty plik testowy:
{-# LANGUAGE ForeignFunctionInterface #-}
-- printTest.hs
import Foreign
import Foreign.C.Types
import Foreign.C.String
import qualified Data.ByteString.Char8 as B
---
foreign import ccall unsafe "myprint.h myprint" c_myprint :: CString -> IO()
---
main = B.useAsCString (B.pack "Tempura is great!") c_myprint
udało mi się skompilować ten wykonując:
ghc --make myprint.c printTest.hs
i uzyskać plik wykonywalny, ale Nie byłem w stanie załadować go w ogóle w ghci. To znacznie opóźnia proces testowania.
_Question 2_ Co muszę zrobić, aby załadować kod Haskell w ghci który wiąże się mojego kodu C? Żadne z głównych źródeł informacji FFI nie miało nic do powiedzenia na ten temat. Żadna liczba manipulacji przy użyciu ghci -L
nie sprawi, że zadziała.
Serdecznie dziękuję za wszelką pomoc, jaką możesz zaoferować.
Q2, musisz skompilować myprint.c jako bibliotekę, jeśli chcesz ją załadować w ghci. To zależy od kompilatora/os. – Jonke
Wzdłuż tych linii (gcc -c -fPIC foo.c -o foo.o, a następnie gcc -shared -Wl, -soname, libfoo.so.1 -o libfoo.so.1.0.1 foo.o) lub coś w stylu ten – Jonke