1
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Organization

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

今回の環境

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

関連記事

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
1
Help us understand the problem. What are the problem?