수색…


통사론

  • 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호출 규칙을 참조합니다. 현재 ccallstdcall (파스칼 규칙)이 지원됩니다. 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


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow