Doubleの代わりに任意精度の浮動小数点/ドロップを作成するために、FFIを使用してMPFRをラップしようとしていますが、すべての努力にもかかわらず、最も単純なコードは機能しません。コンパイルして実行しますが、しばらく動作するふりをした後、嘲笑してクラッシュします。単純なCバージョンのコードは、数値「1」から(小数点以下640桁)までの合計10,000回をうまく出力します。Haskellバージョンは、同じことをするように求められた場合、「1.0000 ... 0000」の289回の印刷後、および385回の印刷後、アサーションの失敗と爆弾を引き起こし、データをサイレントに破損(?)します。「動作するはず」なので、これをデバッグする方法がわかりません。
コードはhttp://hpaste.org/10923で閲覧でき、 http: //www.updike.org/mpfr-broken.tar.gzでダウンロードできます。
FreeBSD6ではGHC6.83を、Mac OSXではGHC6.8.2を使用しています。ライブラリとヘッダーファイルの正しいパス(Makefileを変更)とともにMPFR(2.3.2でテスト済み)をインストールする必要があることに注意してください。 GMPから)これを正常にコンパイルします。
質問
なぜCバージョンは機能するのに、Haskellバージョンはフレークアウトするのですか?FFIに近づくときに他に何が欠けていますか?StablePtrsを試しましたが、まったく同じ結果になりました。
他の誰かが私のコードをコンパイルして実行することにより、これがMac / BSDのみの問題であるかどうかを確認できますか?(Cコードは「機能」しますか?Haskellコードは「noworks」は機能しますか?)LinuxとWindowsの誰かがコンパイル/実行して、同じ結果が得られるかどうかを確認できますか?
Cコード:(works.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmp.h>
#include <mpfr.h>
#include "mpfr_ffi.c"
int main()
{
int i;
mpfr_ptr one;
mpf_set_default_prec_decimal(640);
one = mpf_set_signed_int(1);
for (i = 0; i < 10000; i++)
{
printf("%d\n", i);
mpf_show(one);
}
}
Haskellコード:(Main.hs---動作しません)
module Main where
import Foreign.Ptr ( Ptr, FunPtr )
import Foreign.C.Types ( CInt, CLong, CULong, CDouble )
import Foreign.StablePtr ( StablePtr )
data MPFR = MPFR
foreign import ccall "mpf_set_default_prec_decimal"
c_set_default_prec_decimal :: CInt -> IO ()
setPrecisionDecimal :: Integer -> IO ()
setPrecisionDecimal decimal_digits = do
c_set_default_prec_decimal (fromInteger decimal_digits)
foreign import ccall "mpf_show"
c_show :: Ptr MPFR -> IO ()
foreign import ccall "mpf_set_signed_int"
c_set_signed_int :: CLong -> IO (Ptr MPFR)
showNums k n = do
print n
c_show k
main = do
setPrecisionDecimal 640
one <- c_set_signed_int (fromInteger 1)
mapM_ (showNums one) [1..10000]