LoginSignup
3
1

More than 3 years have passed since last update.

mainの無いFortranのコードをCのコードから呼び出して動かす

Last updated at Posted at 2018-06-14

今回の環境

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の指定も必要だった。

関連記事

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1