Haskell Language
외부 함수 인터페이스
수색…
통사론
- foreign import ccall unsafe "foo"hFoo :: Int32 -> IO Int32 {- 어떤 오브젝트 파일에서
foo
라는 이름의 함수를 임포트하고 Haskell 코드로 호출 할 수있는 기호hFoo
를 정의합니다. -}
비고
Cabal은 하스켈 패키지에 C 및 C ++ 라이브러리를 포함하는 것을 지원하지만 몇 가지 버그가 있습니다. 첫째, ao
사용되는 bo
정의 된 데이터 (함수가 아닌)가 있고 C-sources: ac, bc
나열하면 cabal은 데이터를 찾을 수 없습니다. 이것은 # 12152에 문서화되어 있습니다. Cabal을 사용할 때 C-sources
목록을 C-sources: bc, ac
C-sources
로 재주문하는 것이 좋습니다. C-sources: bc, ac
. 스택을 사용할 때 스택은 항상 목록의 순서에 관계없이 C-sources
사전 순으로 링크하기 때문에 스택을 사용할 때이 기능이 작동하지 않을 수 있습니다.
또 다른 문제점은 헤더 (.h) 파일의 C ++ 코드를 #ifdef __cplusplus
guard로 둘러 #ifdef __cplusplus
한다는 것입니다. 이것은 GHC가 헤더 파일의 C ++ 코드를 이해하지 못하기 때문입니다. 헤더 파일에 C ++ 코드를 작성할 수는 있지만 가드로 둘러싸 야합니다.
ccall
은 호출 규칙을 참조합니다. 현재 ccall
및 stdcall
(파스칼 규칙)이 지원됩니다. unsafe
키워드는 선택적입니다. 이것은 단순 기능의 오버 헤드를 감소 시키지만, 외부 기능 블록이 무기한 또는 실행할 수있는 권한이있는 경우 데드락이 발생할 수 1 .
하스켈에서 C 호출하기
성능상의 이유로 또는 성숙한 C 라이브러리가 있기 때문에 하스켈 프로그램에서 C 코드를 호출 할 수 있습니다. 다음은 C 라이브러리에 데이터를 전달하고 응답을 얻는 간단한 예제입니다.
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
키워드는 'safe'보다 효율적인 호출을 생성하지만, C 코드가 Haskell 시스템에 콜백을하지 않아야합니다. foo
는 완전히 C 언어를 사용하고 Haskell을 절대 호출하지 않기 때문에 unsafe
수 있습니다.
우리는 C 언어로 cabal에게 컴파일하고 링크하도록 지시해야합니다.
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
Haskell을 C 코드의 콜백 함수로 전달.
C 함수가 다른 함수에 대한 포인터를 인수로 받아들이는 것은 매우 일반적입니다. 가장 보편적 인 예제는 일부 GUI 툴킷 라이브러리에서 버튼을 클릭 할 때 실행될 동작을 설정하는 것입니다. 하스켈 함수를 C 콜백으로 전달할 수 있습니다.
이 C 함수를 호출하려면 :
void event_callback_add (Object *obj, Object_Event_Cb func, const void *data)
먼저 Haskell 코드로 가져옵니다.
foreign import ccall "header.h event_callback_add"
callbackAdd :: Ptr () -> FunPtr Callback -> Ptr () -> IO ()
이제 Object_Event_Cb
가 C 헤더에 정의 된 방법을 Object_Event_Cb
보고 Haskell에 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
을 해제하는 것이 중요합니다.
freeHaskellFunPtr cbPtr