2017-12-04 29 views
2

Int# 세 외국 함수 호출에서 스택에 반환 할 수있는 방법이 있습니까? 이 (# Int#, Int#, Int# #) 때문에 컴파일되지 않습니다FFI : 스택에 세 Int # '을 반환합니다

struct Tuple { 
    int bezout1, bezout2, gcd; 
} 

struct Tuple extendedGcd(int a, int b) { 
    /* elided */ 
} 

ccall 지원하지 않습니다 :

여기에 (내가 실제로 관심이있는 것과 오브젝트 파일과 동등한를 생성 또는 C 코드) C 코드

,321 다음 SEG-오류 ( MagicHash, GHCForeignImportPrim, ForeignFunctionInterface, UnboxedTuplesMagicHash 불구, 컴파일 된) 다음의
foreign import ccall "extendedGcd" 
    extendedGcd :: Int# -> Int# -> (# Int#, Int#, Int# #) 

내 모든 사용 0 나는 문제의이 종류를 해결하기 위해 어떤 노력이 있었다 몇 가지 증거를 찾을 수 있습니다

:

나는 이것이 상상 (같은 사람)

+0

가져올 C 함수의 유형은 무엇입니까? C 타입의 타입은 Haskell에서 어떤 타입을 할당 할 수 있는지를 완전히 결정한다고 생각합니다. 'ccall'은 C 호출 규칙을 모델링하기위한 것입니다; C 자체에는 다중 리턴이라는 개념이 없기 때문에'ccall'에도 존재하지 않습니다. 자동 struct marshalling에 대한 제안은'c2hs' 등을 사용하여 구조체를 마샬링하기위한 코드를 자동으로 생성하는 데 유리하게 사용되었다고 생각합니다. – user2407038

+0

@ user2407038 확실히 C 타입 (일부 코드 포함)을 가지고 있지만'Storable' 인스턴스'c2hs'는 포인터를 전달한다고 가정합니다. 여기에 unboxed 제품 (스택에 3 개의 raw ints 만 전달)을 전달하려고합니다. 나의 이해는 하스켈에서 그렇게하는 유일한 방법은 unboxed 튜플을 통해서이다. – Alec

+0

사실 임시 메모리를 어딘가에 할당하지 않고 C 함수에서 구조체를 반환하는 쉬운 방법은 없습니다. 이것이 성능상의 불이익 (또는 그렇게하는 다른 장애물)이라면, 유일한 옵션은'prim'을 사용하고 unboxed 튜플을 반환하는 것입니다. 그러나 함수가 일반적인 C 함수라면,'prim' 함수가 사용해야하는 GHC 호출 규칙을 따르지 않을 것입니다. 함수 주위에 C-- 래퍼 (wrapper)를 써야합니다. – user2407038

답변

1

C에서 직접 어셈블리로 프로 시저를 구현할 수 있다면 꽤 쉽게 할 수 있습니다. 참조 : http://brandon.si/code/almost-inline-asm-in-haskell-with-foreign-import-prim/. 어쩌면 GCD 알고리즘이 괜찮을거야.

here을 함께 넣은 완성 된 프로젝트가 있습니다.

+2

아, 이것은 실제로 GCD를위한 것이 아닙니다. 이것은 녹스 튜플을 사용하여 Haskell interop을 생성하기위한 것입니다. :) 그럼에도 불구하고 이것은 유용합니다! 감사합니다. – Alec