2

重複の可能性:
FFI は配列を処理できますか? もしそうなら、どのように?

Haskell で記述された小さなアセンブラがあります。これは、アセンブリ コードを含む文字列を受け取り、バイナリ マシン コードの文字列を返します。この Haskell ライブラリを共有ライブラリとしてビルドすることで、C でこの関数を使用できるようにしたいと考えています。バイナリ マシン コードには null 値を含めることができるためCString、通常の null で終わる文字列であるため、戻り値の型として使用できません。CStringLenまた、FFI では a を戻り値として使用できないためです。

これを達成するには、どのタイプを使用する必要がありますか?

内部アセンブリ関数の型シグネチャ:

assembly :: String -> ByteString 

この関数の入力と出力の例を次に示します。

入力:

decl r0 0x02
decl r1 0x10
add r0 r1 
mov rr rs

出力 (1 行あたり 3 バイトの 16 進数で表されるバイナリ データ):

01 00 02
01 01 10
03 00 01
02 05 04
4

3 に答える 3

3

もし私が C で書いていたら、次のようなプロトタイプを与えるかもしれません:

void assemble(char **out, size_t *outlen, const char *in);

これは次のように変換されます (未テスト):

import qualified Assemble -- your module with the "assemble" function

import Foreign.Ptr (Ptr)
import Foreign.Storable (poke)
import Foreign.Marshal.Utils (copyBytes)
import Foreign.Marshal.Alloc (mallocBytes)
import Foreign.C.Types (CSize, CChar)
import Foreign.C.String (CString, peekCString)
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)

foreign export ccall assemble :: Ptr (Ptr CChar) -> Ptr CSize -> CString -> IO ()

assemble :: Ptr (Ptr CChar) -> Ptr CSize -> String -> IO ()
assemble out outlen instrptr = do
  instr <- peekCString instrptr
  unsafeUseAsCStringLen (Assemble.assemble instr) $ \(p, n) -> do
    outval <- mallocBytes n
    copyBytes outval p n
    poke out outval
    poke outlen (fromIntegral n)

これはデータを領域にコピーしますmalloc。これは「安全」であり、C コードはそれを解放するために特別なことをする必要がないため ( free().

于 2012-09-30T14:26:48.043 に答える
1

生のポインタと手動のメモリ割り当てで何かできるでしょうか?(を参照してくださいForeign.Marshal.Alloc。)mallocメモリのチャンクだけで、そこにバイナリデータを書き込むことができるようです...

于 2012-09-30T14:24:04.580 に答える
0

私は Haskell について確信が持てるほどよく知りませんが、追加の out パラメータの長さを haskell 関数に渡すことはできませんか? 関数から戻ると、長さは返される文字列のサイズを c プログラムに伝えます。私はcとpythonの間で同様のことをしたと思います。

または、長さフィールドを持つ c++ 文字列のようなカスタム オブジェクトを返すことはできませんか。純粋なcを使用している場合でも、cとhaskellの間で型を共有する方法である場合(存在するはずです)、char配列と長さフィールドを持つ小さな文字列構造体を記述し、haskellからそのオブジェクトを返すことができます.

于 2012-09-30T09:57:27.640 に答える