Haskell:#define-d定数の値を取得するにはどうすればよいですか?
質問
Haskellプログラムで、Cヘッダーで定義された定数を使用する最良の方法は何ですか?
解決
このタスクでは、 hsc2hs が友人。
簡単な例として、から INT_MAX
の値を取得しましょう limits.h
。
$ cat >IntMax.hsc
module Main where
#include <limits.h>
c_INT_MAX = #const INT_MAX
main = print c_INT_MAX
hsc2hsを使用すると、ヘッダーを #include
し、 #const
ディレクティブで定数の値を使用できます。
手作業で構築する代わりに、Cabalを使用します:
$ cat >intmax.cabal
Name: intmax
Version: 0.0
Cabal-Version: >=1.2
Build-Type: Simple
Executable intmax
Main-Is: IntMax.hs
Build-Depends: base
メインプログラムの名前が IntMax.hsc
であっても、 Main-Is
行は IntMax.hs
を指していることに注意してください。 Cabalが IntMax.hs
を探して IntMax.hsc
を見つけると、ビルドの一部としてhsc2hsを介して後者を自動的にフィードします。
$ cabal configure
Resolving dependencies...
Configuring intmax-0.0...
$ cabal build
Prerocessing executables for intmax-0.0...
Building intmax-0.0...
[1 of 1] Compiling Main ( dist\build\intmax\intmax-tmp\IntMax.hs, dist\build\intmax\intmax-tmp\Main.o )
Linking dist\build\intmax\intmax.exe ...
$ ./dist/build/intmax/intmax
2147483647
複数の定数で行を分割することに注意してください。 FormatMessage に渡すビットフィールドを組み立てているとします。次のように記述します
flags = #const FORMAT_MESSAGE_FROM_SYSTEM
.|.
#const FORMAT_MESSAGE_IGNORE_INSERTS
すべてを1行に入力すると、構文エラーが発生します。
他のヒント
GHCは、可能な限り -fvia-c
から -fasm
に向かっています。
1つの副作用は、 -fvia-c
モードであっても、Cヘッダーをまったく使用せずにプログラムをコンパイルできることです。これにより、コンパイル結果がGHC -fasm
モード。
したがって、 hsc2hs
、 c2hs
、またはGHCがソースをコンパイルする前に 実行する他のプリプロセッサを使用する必要があります。
c2hs
はネイティブに enum
定数をサポートしています...しばらくの間ですが、このようなことが正しいと思います。
#c
enum Foo = { Bar, Baz };
void something(enum Foo foo) {}
#endc
{#enum Foo#}
somethingBar = {#call pure something#} (cFromEnum Bar)
#define
'd定数は、非常に複雑です。常にインラインでコピーするか、追加のCを使用して列挙型またはconst変数に変換しました。