5

Fortran から C API 関数を呼び出したいです。C 関数は、バイト配列を受け入れます。

void image(const void *bitmap, int w, int h);

ここで、連続する 3 バイトは*bitmapRGB カラー トリプルを表し、C のように解釈されます。Fortran でunsigned charビットマップを初期化し、C 内で描画を処理したいと考えています。Fortran での現在の定義は使用しています

integer*1 rgbImage(6,2)

たとえば、2x2 のイメージを初期化しますが、コンパイラは代入を受け入れません

rgbImage(1,1) = 255

赤い色を得るために。BYTE符号なしの 1 バイトに, UNSIGNED*1,を使用するというヒントを見たことがありLOGICAL*1ますが、gfortran (Mac OS X での MacPort の gcc 4.4 または 4.6) は、どちらにもあまり満足していません。-1チートしての代わりに値を代入することでおそらく回避できます255が、それは非常に使いにくいです。コンパイラ フラグ-fno-range-checkはコードのコンパイルに役立ちましたが、他の Fortran コンパイラでは使用できない可能性があり、私はそれを醜い解決策と考えています (他の警告をキャッチしたい場合もあります)。値'FF'Xまたは'11111111'Bも 32 ビット整数として認識されます。

コードがさまざまな Fortran コンパイラ間で移植可能であることが強く望まれます。

4

2 に答える 2

13

私の提案はCHARACTER、変数を使用ACHARし、値を設定するために使用することです(ICHAR必要に応じて整数に戻すこともできます)。これにより、必要なものが得られ、完全に移植可能になります。例えば、

character, dimension(6,2) :: rgbImage

rgbImage(1,1) = achar(255)

追加して更新: Fortran 2003 の iso_c_binding を使用して C ルーチンに接続する場合 (強くお勧めします!)、その rgbImage 配列の文字を kindc_char

character(kind=c_char), dimension(6,2) :: rgbImage
integer(kind=c_int) :: w, h

...
rgbImage(1,1) = achar(255)
...

call image(rgbImage, w, h)

ルーチンのインターフェースを定義した場所

 interface
    subroutine image(img, w, h) bind(C)
       use, intrinsic :: iso_c_binding
       implicit none
       integer(kind=c_int), intent(in), value :: w, h
       character(kind=c_char) :: img(:,:)
    end subroutine image
 end interface
于 2012-05-25T14:18:30.017 に答える
0

状況によっては、1 バイトの c int 配列を iVal(:) などの Integer(1) 配列に渡してから、Integer(2) iVal2(:) などの別の Int 配列を作成するという方法もあります。それから:

Where(iVal(:) < 0)
    iVal2(:) = -iVal(:)+127
ElseWhere
    iVal2(:) = iVal(:)
End Where

...これは、文字への/からの変換に比べて少し効率的/クリーンになり(場合によって)、必要なコーディングが少なくなります(場合によって)。

この種のことをたくさん行う場合 (さまざまなタイプの ussigned などを Fortran に接続する場合)、Fortran のビット組み込み関数に依存するいくつかのユーティリティ ルーチン (たとえば、BTest()、iBSet() など) に投資する価値があるかもしれません。

于 2014-02-12T22:12:53.473 に答える