Haskell Language
विदेशी फ़ंक्शन इंटरफ़ेस
खोज…
वाक्य - विन्यास
- विदेशी आयात ccall असुरक्षित "foo" hFoo :: Int32 -> IO Int32 {- कुछ ऑब्जेक्ट फ़ाइल में
foo
नामक एक फ़ंक्शन को आयात करता है, और प्रतीकhFoo
को परिभाषित करता है जिसे हास्केल कोड के साथ कहा जा सकता है। -}
टिप्पणियों
जबकि कैबल को हास्केल पैकेज में C और C ++ लाइब्रेरी शामिल करने के लिए समर्थन है, कुछ बग हैं। पहले, यदि आपके पास bo
में परिभाषित डेटा (एक फ़ंक्शन के बजाय) है जो ao
में उपयोग किया जाता है, और C-sources: ac, bc
सूची C-sources: ac, bc
, तो केबल डेटा को खोजने में असमर्थ होंगे। यह # 12152 में प्रलेखित है। कैबल का उपयोग करते समय एक वर्कअराउंड C-sources
सूची को C-sources
करने के लिए फिर से चालू करना C-sources
C-sources: bc, ac
। स्टैक का उपयोग करते समय यह काम नहीं कर सकता है, क्योंकि स्टैक हमेशा C-sources
वर्णानुक्रम से जोड़ता है, भले ही आप उन्हें जिस क्रम में सूचीबद्ध करते हैं।
एक अन्य समस्या यह है कि आपको हेडर (.h) फाइलों में किसी भी C ++ कोड को #ifdef __cplusplus
गार्ड के साथ #ifdef __cplusplus
। ऐसा इसलिए है क्योंकि GHC हेडर फ़ाइलों में C ++ कोड को नहीं समझता है। आप अभी भी हेडर फ़ाइलों में सी ++ कोड लिख सकते हैं, लेकिन आपको इसे गार्ड के साथ घेरना होगा।
ccall
कॉलिंग कन्वेंशन को संदर्भित करता है; वर्तमान में ccall
और stdcall
(पास्कल सम्मेलन) समर्थित हैं। unsafe
कीवर्ड वैकल्पिक है; इस सरल कार्यों के लिए भूमि के ऊपर कम कर देता है, लेकिन गतिरोध का कारण हो सकता है, तो विदेशी समारोह ब्लॉक अनिश्चित काल के लिए या निष्पादित करने के लिए अपर्याप्त अनुमति है 1 ।
हास्केल से कॉलिंग सी
प्रदर्शन कारणों से, या परिपक्व सी पुस्तकालयों के अस्तित्व के कारण, आप सी कोड को हास्केल कार्यक्रम से कॉल करना चाह सकते हैं। यहां एक सरल उदाहरण है कि आप सी लाइब्रेरी में डेटा कैसे पास कर सकते हैं और एक उत्तर प्राप्त कर सकते हैं।
foo.c:
#include <inttypes.h>
int32_t foo(int32_t a) {
return a+1;
}
Foo.hs:
import Data.Int
main :: IO ()
main = print =<< hFoo 41
foreign import ccall unsafe "foo" hFoo :: Int32 -> IO Int32
unsafe
कीवर्ड 'सुरक्षित' की तुलना में अधिक कुशल कॉल उत्पन्न करता है, लेकिन इसके लिए आवश्यक है कि सी कोड कभी भी हास्केल सिस्टम को कॉलबैक न करे। चूंकि foo
पूरी तरह से सी में है और हास्केल को कभी नहीं बुलाएगा, इसलिए हम unsafe
उपयोग कर सकते हैं।
हमें सी स्रोत में संकलन और लिंक करने के लिए केबल को निर्देश देने की भी आवश्यकता है।
foo.cabal:
name: foo
version: 0.0.0.1
build-type: Simple
extra-source-files: *.c
cabal-version: >= 1.10
executable foo
default-language: Haskell2010
main-is: Foo.hs
C-sources: foo.c
build-depends: base
तब आप चला सकते हैं:
> cabal configure
> cabal build foo
> ./dist/build/foo/foo
42
हास्केल पासिंग सी कोड में कॉलबैक के रूप में कार्य करता है।
सी फ़ंक्शंस के लिए दूसरे कार्यों को तर्क के रूप में स्वीकार करना बहुत आम है। जब जीयूआई टूलकिट लाइब्रेरी में किसी बटन पर क्लिक किया जाता है, तो सबसे लोकप्रिय उदाहरण एक एक्शन को निष्पादित करना है। सी कॉलबैक के रूप में हास्केल कार्यों को पारित करना संभव है।
इस C फ़ंक्शन को कॉल करने के लिए:
void event_callback_add (Object *obj, Object_Event_Cb func, const void *data)
हम पहले इसे हास्केल कोड में आयात करते हैं:
foreign import ccall "header.h event_callback_add"
callbackAdd :: Ptr () -> FunPtr Callback -> Ptr () -> IO ()
अब देख रहे हैं कि Object_Event_Cb
को C हैडर में कैसे परिभाषित किया जाता है, यह परिभाषित करें कि हास्केल में Callback
क्या है:
type Callback = Ptr () -> Ptr () -> IO ()
अंत में, एक विशेष समारोह में उस प्रकार की हास्केल समारोह लपेटो जाएगा बनाने Callback
एक सूचक में FunPtr Callback
:
foreign import ccall "wrapper"
mkCallback :: Callback -> IO (FunPtr Callback)
अब हम C कोड के साथ कॉलबैक रजिस्टर कर सकते हैं:
cbPtr <- mkCallback $ \objPtr dataPtr -> do
-- callback code
return ()
callbackAdd cpPtr
एक बार कॉलबैक FunPtr
बाद, आपको FunPtr
को आवंटित करना महत्वपूर्ण है:
freeHaskellFunPtr cbPtr