Haskell プログラムで、C ヘッダーで定義された定数を使用する最良の方法は何ですか?
2 に答える
このタスクでは、hsc2hsが役に立ちます。
INT_MAX
簡単な例として、 fromの値を取得してみましょう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
、コンパイル結果がモードの GHC と機能的に同一であることを保証するために、モードであっても、C ヘッダーをまったく使用せずにプログラムがコンパイルされる可能性があること-fasm
です。
したがって、 GHC がソースをコンパイルする前にhsc2hs
、 、c2hs
、またはその他のプリプロセッサを実行する必要があります。
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 変数に変換してきました。