今回の環境
Cの処理系: clang
Fortranの処理系: Flang
OS: Linux
Fortranのコード
以下の様なFortranのコードを試した。
arraytest.f90
function array_1d(b,c) bind(c, name = 'array_1d')
implicit none
integer,intent(in),value::b,c
integer::array_1d,k
integer a(0:3)
complex(kind(0d0))::ca(0:100)
a(0) = b
a(1) = c
a(2) = b+c
a(0) = a(0)*a(2)
a(1) = a(1)*a(2)
ca=cmplx(0d0,0d0,kind=8);
do k=1,3
ca(k)=k+ca(k)
enddo
array_1d= a(1) + a(2) + real(ca(2))
end function
ポイント
bind(c, name = 'array_1d')
でCで参照する際の関数名を明示しておくのが吉。
integer,intent(in),value::b,c
Fortranは参照渡しが基本なので、Cから呼べるように
値渡しを指定する。
Cのコード
先ほどのFortran内のarray_1d関数を呼び出すだけの以下のコードを用意。
#include <stdio.h>
extern int array_1d();
int main(int argc,char**argv) {
printf("array_1d = %d\n",array_1d());
}
ビルド方法
flang -c arraytest.f90
-cを指定することで、.oまでの作成になるので、main関数がなくても
flangに怒られなくなる。
clang -c atest.c
clang -o atest atest.o arraytest.o
そこそこ数値計算するようなケース
次に、以下のコードで試した。
cmplxchk.f90
module m_zeta
contains
function zeta3(sr,si) bind(c, name = 'zeta3')
implicit none
complex(kind(0d0)),external ::mymain
double precision,value::sr,si
double precision::zeta3,rr,ri
complex(kind(0d0))::s,tt
s = cmplx(sr, si)
tt= mymain(s)
rr = real(tt)
ri = aimag(tt)
zeta3 = rr + ri
contains
function mymain(s)
implicit none
complex(kind(0d0)),intent(in)::s
complex(kind(0d0))::mymain
mymain = sin(s)
end function mymain
end function zeta3
end module m_zeta
btest.c
#include <stdio.h>
extern double zeta3(float x,float y);
int main(int argc,char**argv) {
printf("ans = %lf3.8\n",zeta3(0.5,-14.0));
}
flang -c cmplxchk.f90
clang -c btest.c
clang -o btest btest.o cmplxchk.f90
と同様にすると、以下の様にリンクに失敗する。
cmplxchk.o: In function `m_zeta_zeta3_mymain':
/root/cmplxchk.f90:23: undefined reference to `__mth_i_cdsin'
clang-5.0: error: linker command failed with exit code 1 (use -v to see invocation)
そこで、
clang -o btest btest.o cmplxchk.o /root/miniconda3/lib/libflang.a -lm
と、flangのランタイムライブラリとlibm.soを指定すると
無事に実行バイナリが生成される。
ここに挙げたFortranoのコードでは不要であったが
別件で自分が試したケースだと
clang -o btest btest.o zeta4.o /root/miniconda3/lib/libflang.a /root/miniconda3/lib/libflangrti.a -lm
というように、libflang.aの他にlibflangrti.aの指定も必要だった。