Windows Vista Home PremiumにFTN95をインストールしたPCにて、Fortranのプログラミングをし始め、「Cpad for Salford FTN77」を利用してプログラミングをしています(FORTRAN77・Fortran90ともに)。FTN95でのFortranプログラミングに際し、FortranプログラムからC言語で実装された関数を呼ぶには、どのように対処すれば可能になりますでしょうか?
ユーザーガイドによれば、「Fortranプログラム中に、C_EXTERNALという宣言をした関数は、Cの関数と同じくアクセスできるようになり、C側では、#extern <返り値>関数名(引数)を与えれば、Cの関数として呼び込むことができる。」とのことがかかれています。
実際に使っているファイルをいくつか書き出します。
<D:\fortran\sample.f>
C_EXTERNAL WRITE 'WriteFile' : INTEGER*4
INTEGER*4 RESULT
RESULT=WRITE()
write(*,*) result
return
end
<D:\fortran\sample.c>
#extern int Writefile(int);
<C:\Program Files\Silverfrost\FTN95\ftn95c.bat>
ftn95.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 /link
ちなみに、「Cpad for Salford FTN77」での実行/設定/実行/コンパイル時のパラメータは「/link /dreal」です。もちろんftn95.exeへのパスは通してあります。何が問題でしょうか?
何分初心者ですので、拙い質問かと思いますが、何卒ご教示願います。
No.8ベストアンサー
- 回答日時:
ftn77 と ftn95 で違ったりするみたいですね。
コンパイルオプションでどうにかなるのかもしれませんが、とりあえずC側のファイルの関数名を
hello から HELLO のように全部を大文字にしてください。
これでリンクが通るようになると思います。
この回答への補足
貴殿のアドバイスのお陰で無事当方で実行したいことが可能になりました。試行錯誤の結果、ftn95のパラメータには今回のケースでは「/dreal」だけでなく「/ckc」もいるということがわかり、下記の通り、sccでもgccでも共に無事成功しました。何度も何度も拙い質問に堪えながらの回答ありがとうございました。またわからないことが生じましたら、そのときは再度アドバイスよろしくお願いいたします。
D:\math\fortran>ftn95 /dreal /ckc tes1.f
[FTN95/Win32 Ver. 5.01.0 Copyright (c) Silverfrost Ltd 1993-2006]
NO ERRORS [<main program> FTN95/Win32 v5.01.0]
D:\math\fortran>scc lib.c
[Silverfrost SCC/WIN32 Ver 3.65 Copyright (c) Silverfrost Ltd 2006]
NO ERRORS [<LIB> SCC/WIN32 Ver 3.65]
D:\math\fortran>type tes1.f
implicit double precision(a-h, o-z)
C_EXTERNAL near
C_EXTERNAL down
C_EXTERNAL up
C_EXTERNAL chop
C_EXTERNAL hello
dimension a(100),b(100)
cn=0.0d0
cu=0.0d0
cd=0.0d0
cc=0.0d0
do i=1,100
a(i)=0.1d0
b(i)=0.1d0
end do
call near
do i=1,100
cn=cn+a(i)*b(i)
end do
call up
do i=1,100
cu=cu+a(i)*b(i)
end do
call down
do i=1,100
cd=cd+a(i)*b(i)
end do
call chop
do i=1,100
cc=cc+a(i)*b(i)
end do
write(6,10) cn,cu
write(*,*)
write(6,10) cd,cc
10 format(f26.19,2x,f26.19)
call near
end
D:\math\fortran>type lib.c
#include <stdio.h>
int _RoundNear =0x133a;
int _RoundDown =0x173a;
int _RoundUp =0x1b3a;
int _RoundChop =0x1f3a;
extern "C" void NEAR(void)
{
asm{fldcw _RoundNear};
printf("%s\n", "Near");
}
extern "C" void DOWN(void)
{
asm{fldcw _RoundDown};
printf("%s\n", "Down");
}
extern "C" void UP(void)
{
asm{fldcw _RoundUp};
printf("%s\n", "Up");
}
extern "C" void CHOP(void)
{
asm{fldcw _RoundChop};
printf("%s\n", "Chop");
}
D:\math\fortran>slink tes1.obj lib.obj
Creating executable: D:\math\fortran\tes1.exe
D:\math\fortran>tes1
Near
Up
Down
Chop
1.0000000000000006661 1.0000000000000008882
0.9999999999999934497 0.9999999999999934497
Near
D:\math\fortran>type lib2.c
#include <stdio.h>
int _RoundNear =0x133a;
int _RoundDown =0x173a;
int _RoundUp =0x1b3a;
int _RoundChop =0x1f3a;
void NEAR()
{
asm volatile("fldcw __RoundNear");
printf("%s\n", "Near");
}
void DOWN()
{
asm volatile("fldcw __RoundDown");
printf("%s\n", "Down");
}
void UP()
{
asm volatile("fldcw __RoundUp");
printf("%s\n", "Up");
}
void CHOP()
{
asm volatile("fldcw __RoundChop");
printf("%s\n", "Chop");
}
void HELLO()
{
printf("%s\n", "hello from C function!");
}
D:\math\fortran>gcc -c lib2.c
D:\math\fortran>slink tes1.obj lib2.o
Creating executable: D:\math\fortran\tes1.exe
D:\math\fortran>tes1
Near
Up
Down
Chop
1.0000000000000006661 1.0000000000000008882
0.9999999999999934497 0.9999999999999934497
Near
D:\math\fortran>
貴殿のアドバイスのお陰で無事当方で実行したいことが可能になりました。試行錯誤の結果、ftn95のパラメータには今回のケースでは「/dreal」だけでなく「/ckc」もいるということがわかり、sccでもgccでも共に無事成功しました。何度も何度も拙い質問に堪えながらの回答ありがとうございました。またわからないことが生じましたら、そのときは再度アドバイスよろしくお願いいたします。
No.7
- 回答日時:
>パスを通した上でコマンドプロンプトから「gcc lib.c」とするとエラーとなり、
ここで、gcc -c lib.c
のようにしてください。
これをつけないとlib.cだけで実行ファイルを作りに行ってしまうので
それが理由でエラーになります。
あれ、でも#3の補足を見るとオブジェクトファイルが、とかあるなあ。
まあそれはおいといて、
-cをつけると、(エラーがなければ)lib.o を作って終わりますから
Fortranのソースからできた sample.obj と一緒にリンクしてください。
あ、Fortranのコンパイルも
ftn95.exe /link /dreal sample.f /link
の /link は指定しないでくださいね。
ftn95 dreal sample.f
gcc -c lib.c
slink sample.obj lib.o
てな手順で sample.exe が最終的に手に入るはずです。
この回答への補足
「gcc -c」で対処しても下記の通りうまくいきませんでしたので、「scc」でやってみましたが結局現状ではどちらも当方ではうまく動きません。
D:\math\fortran>type tes1.f lib.c
tes1.f
program mogera
C_EXTERNAL hello
call hello
stop
end
lib.c
#include <stdio.h>
#define near() asm volatile("fldcw __RoundNear")
#define down() asm volatile("fldcw __RoundDown")
#define up() asm volatile("fldcw __RoundUp")
#define chop() asm volatile("fldcw __RoundChop")
int _RoundNear =0x133a;
int _RoundDown =0x173a;
int _RoundUp =0x1b3a;
int _RoundChop =0x1f3a;
void hello()
{
printf("%s\n", "hello from C function!");
}
D:\math\fortran>ftn95 /dreal tes1.f
[FTN95/Win32 Ver. 5.01.0 Copyright (c) Silverfrost Ltd 1993-2006]
NO ERRORS [<MOGERA> FTN95/Win32 v5.01.0]
D:\math\fortran>gcc -c lib.c
D:\math\fortran>slink tes1.obj lib.o
WARNING the following symbols are missing:
HELLO D:\math\fortran\tes1.obj
(D:\MATH\FORTRAN\TES1.F)
Creating executable: D:\math\fortran\tes1.exe
D:\math\fortran>tes1
D:\math\fortran>type error.txt
Runtime error from program:d:\math\fortran\tes1.exe
Run-time Error
*** Error 29, Call to missing routine : _HELLO at 0x00401020.
00401000 main [+0025] [recur= 1]
D:\math\fortran>
重要な点を含んだ回答していただき、ありがとうございます。何度も何度も回答していただいているにも関わらず、当方での動作がうまくいかず「再質問→再回答」の繰り返しとなっていること、申し訳なく思います。
さて、プログラムのほうは貴殿のようにうまく動きません。少なくとも「tes1.f」・「lib.c」についてはそれぞれ「ftn95」・「scc」で単体でなら何のエラーも返さずにコンパイルできます。しかし、「slink」の段階でWarningが出てきてしまい、実行ファイルができるにはできてもエラーになってしまいます。どのようにすれば対処できますでしょうか?
D:\math\fortran>type tes1.f lib.c
tes1.f
program mogera
C_EXTERNAL hello
call hello
stop
end
lib.c
#include <stdio.h>
#define near() asm volatile("fldcw __RoundNear")
#define down() asm volatile("fldcw __RoundDown")
#define up() asm volatile("fldcw __RoundUp")
#define chop() asm volatile("fldcw __RoundChop")
int _RoundNear =0x133a;
int _RoundDown =0x173a;
int _RoundUp =0x1b3a;
int _RoundChop =0x1f3a;
void hello()
{
printf("%s\n", "hello from C function!");
}
D:\math\fortran>ftn95 /dreal tes1.f
[FTN95/Win32 Ver. 5.01.0 Copyright (c) Silverfrost Ltd 1993-2006]
NO ERRORS [<MOGERA> FTN95/Win32 v5.01.0]
D:\math\fortran>scc lib.c
[Silverfrost SCC/WIN32 Ver 3.65 Copyright (c) Silverfrost Ltd 2006]
NO ERRORS [<LIB> SCC/WIN32 Ver 3.65]
D:\math\fortran>slink tes1.obj lib.obj
WARNING the following symbols are missing:
HELLO D:\math\fortran\tes1.obj
(D:\MATH\FORTRAN\TES1.
Creating executable: D:\math\fortran\tes1.exe
D:\math\fortran>tes1
D:\math\fortran>type error.txt
Runtime error from program:d:\math\fortran\tes1.exe
Run-time Error
*** Error 29, Call to missing routine : _HELLO at 0x00401020.
00401000 main [+0025] [recur= 1]
D:\math\fortran>
No.6
- 回答日時:
.... 誰だ, 「gcc での~ないといけないのです」なんて中途半端なことを言ったやつは....
「コンパイルするだけ」なら main はいらない. gcc だろうと cl だろうと同じこと. たぶん scc でも同じはずだ.
もちろん「リンクして実行ファイルを作る」ためには main が必要.
「コンパイルする」ことと「リンクして実行ファイルを作ること」とは別です. 区別してください.
>.... 誰だ, 「gcc での~ないといけないのです」なんて中途半端なことを言ったやつは....
>「コンパイルするだけ」なら main はいらない. gcc だろうと cl だろうと同じこと. たぶん scc でも同じはずだ.
パスを通した上でコマンドプロンプトから「gcc lib.c」とするとエラーとなり、何のファイルもはき出されません。実際のエラーメッセージは次の通りです。
C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../libmingw32.a(main.o):main.c:(.text+0xbd): undefined reference to WinMain@16'
collect2: ld returned 1 exit status
「scc」でコンパイルする際に、「asm volatile("...")」 という形でアセンブリコードを埋め込むことができないのならば、sccはどのように記述すればいいのでしょうか?
「FTN95」に「scc」もすでにインストール済みなわけで、すでにあるものの有効活用でいけるところまでいってみたいと思うのです(「むしろ、そっちのほうが難しいんだよ!」と突っ込まれるかもしれませんが…)。
No.5
- 回答日時:
まさかまさかなんだけど, C のソースに「関数 main がある」ってオチはないよね?
回答ありがとうございます。「gcc」でのコンパイルには最低限
int main(){
return 0;
}
がないといけないのです。「FTN95」付属の「scc」ではそうではありませんが…。
部分的には貴殿の“オチ”のとおりかもしれません…。
No.4
- 回答日時:
scc というのがわたしがインストールしたものには入っていなかったので
すぐには確認できませんが、それがCコンパイラなら使えるのではないかと思います。
ただ、asm volatile("...") という形でアセンブリコードを埋め込むことは
できないと思われますので、scc 用の記述に変えるなりしなければならないのではないでしょうか。
もうひとつ、Visual C/C++ ですがExpress edition というものが
無料配布されていて、これを使うことができるでしょう。
Visual Studio 2008 Express Edition の DVD イメージからのインストール
http://www.microsoft.com/japan/msdn/vstudio/expr …
No.3
- 回答日時:
>ご教示願います。
これ、相手に敬意をはらった書き方だと思って書いてます?
ま、それはともかくエラーメッセージにあるようにFORTRAN側の
プログラムからして間違ってますし、C側も補足で出されたのも含めて間違ってます。
C_EXTERNAL WRITE 'WriteFile' : INTEGER*4
INTEGER*4 RESULT
RESULT=WRITE()
write(*,*) result
return
end
サブルーチンでもないのに、returnがあるのは間違いということで
コンパイルできてません。
手元にあって試したのはFTN77ですが、基本的には同様にできるはずです。
C:\win32app\salford>type moge.f
program mogera
C_EXTERNAL hello
call hello
stop
end
というFORTRANプログラムで、helloがCで記述したサブルーチンです。
C:\win32app\salford>ftn77 moge.f
[Salford FTN77/Win32 v4.03, Copyright (c) Salford Software Ltd. 1988-1998]
Licensed to: FTN77 Personal Edition
Department: Non-commercial use only
NO ERRORS [<MOGERA>FTN77 Ver 4.03]
で、C側はこう。
C:\win32app\salford>type lib.c
#include <stdio.h>
int _RoundNear =0x133a;
int _RoundDown =0x173a;
int _RoundUp =0x1b3a;
int _RoundChop =0x1f3a;
void
near()
{
__asm fldcw _RoundNear
}
void
down()
{
__asm fldcw _RoundDown
}
void
up()
{
__asm fldcw _RoundUp
}
void
chop()
{
__asm fldcw _RoundChop
}
void
hello()
{
printf("%s\n", "hello from C function!");
}
C:\win32app\salford>cl -c lib.c
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.
lib.c
C:\win32app\salford>slink.exe moge.obj lib.obj
Creating executable: C:\win32app\salford\moge.exe
C:\win32app\salford>moge
hello from C function!
と、C側の関数の出力がされてます。
FORTRAN側でサブルーチンではなく関数として使うのであれば
多少変わりますが大まかな手順としてはこんな感じになります。
補足にあるCプログラムを見るとgcc用のようですが、FTN77やFTN95って
gccでコンパイルしてできた.oファイルもリンクしてくれるんでしょうか?
>>ご教示願います。
>これ、相手に敬意をはらった書き方だと思って書いてます?
当方の言葉の誤用で貴殿に対して失礼となる書き込みをしてしまったこと、心よりお詫び申し上げます。
本題ですが、FortranからCを呼び出すこと自体は問題なくできました。ありがとうございます。ただ、肝心のgccでコンパイルしたオブジェクトファイルでは、(拡張子をgccでのコンパイル時に「.obj」に指定したとしても)実行ファイルができてもエラーとなってしまいます。「『main』関数が2重に定義されている」とかいうメッセージがslink実行時に出てしまい、できた実行ファイルを実行してもエラーで止まってしまいます。
ちなみにFTN95に同梱されているsccではslink不能なのでしょうか。当方はVisual Studioは有しておりませんので「cl.exe」は当然入っておりません。簡単(?)なCの関数を呼び出すのに、さらに別のソフト(有料?)を入れるという大がかりなことをしないとだめなものなのでしょうか…。
何かいい解決法はないものでしょうか?お教え願います。
No.2
- 回答日時:
エラーメッセージが出ているならそれを書いてください. もちろん「翻訳」なんかしないで, 一字一句そのままで.
ちょっと見た感じだと C の方は特にいじらなくてもいいように見えるけどなぁ....
この回答への補足
上述したエラーメッセージは以下の通りです(一字一句そのままです)。
■D:\math\fortran> ftn95c /link /dreal sample.f
D:\math\fortran>ftn95.exe /link /dreal sample.f /link
[FTN95/Win32 Ver. 5.01.0 Copyright (c) Silverfrost Ltd 1993-2006]
0005) return
*** RETURN cannot be inside a PROGRAM block
1 ERROR [<main program> FTN95/Win32 v5.01.0]
*** Compilation failed
なお、Cを呼び出す必要があるのは、Fortranの命令で浮動小数点をユーザーの希望するタイミングでUp・Down・Chop・Nearできないため、Cから呼び出すことでこれを実現したいからです。
ちなみに、<D:\fortran\sample0.c>も用意してあります。
<D:\fortran\sample0.c>
#include <stdio.h>
#define near() asm volatile("fldcw __RoundNear")
#define down() asm volatile("fldcw __RoundDown")
#define up() asm volatile("fldcw __RoundUp")
#define chop() asm volatile("fldcw __RoundChop")
int _RoundNear =0x133a;
int _RoundDown =0x173a;
int _RoundUp =0x1b3a;
int _RoundChop =0x1f3a;
int main()
{
return(0);
}
改めてご教示願います。
No.1
- 回答日時:
質問者さんの組み合わせはやったことがないのですが
<D:\fortran\sample.c>
#extern int Writefile(int);
C側がこれだけですか?
これだと、Cで関数の実装がされてませんけど。
それから、#extern というのはCコンパイラがエラーにしてしまうような気がするんですがユーザーガイドとやらを読み違えてたりしませんか?
FORTRAN側のプログラムもなんか変だなあ。
この回答への補足
上述したエラーメッセージは以下の通りです(一字一句そのままです)。
■D:\math\fortran> ftn95c /link /dreal sample.f
D:\math\fortran>ftn95.exe /link /dreal sample.f /link
[FTN95/Win32 Ver. 5.01.0 Copyright (c) Silverfrost Ltd 1993-2006]
0005) return
*** RETURN cannot be inside a PROGRAM block
1 ERROR [<main program> FTN95/Win32 v5.01.0]
*** Compilation failed
なお、Cを呼び出す必要があるのは、Fortranの命令で浮動小数点をユーザーの希望するタイミングでUp・Down・Chop・Nearできないため、Cから呼び出すことでこれを実現したいからです。
ちなみに、<D:\fortran\sample0.c>も用意してあります。
<D:\fortran\sample0.c>
#include <stdio.h>
#define near() asm volatile("fldcw __RoundNear")
#define down() asm volatile("fldcw __RoundDown")
#define up() asm volatile("fldcw __RoundUp")
#define chop() asm volatile("fldcw __RoundChop")
int _RoundNear =0x133a;
int _RoundDown =0x173a;
int _RoundUp =0x1b3a;
int _RoundChop =0x1f3a;
int main()
{
return(0);
}
改めてご教示願います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) FORTRAN77の配列(除算) 2 2023/02/01 14:34
- その他(プログラミング・Web制作) Fortranでの出力ファイル 2 2023/03/21 21:25
- IT・エンジニアリング FORTRAN、COBOL、C、Java、C++とか誰が作ったのですか?言語習い使いまた出て、キリが 4 2023/05/06 23:11
- C言語・C++・C# C言語 3 2022/10/04 15:07
- 計算機科学 fortranという言語は今でも科学技術計算でPythonと同じくらい使われてると聞いたのですが、そ 10 2022/08/25 00:43
- C言語・C++・C# このプログラミングの問題を教えて欲しいです。 キーボードから整数kを入力し、kが配列aの中に何個存在 2 2022/12/19 22:50
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# 至急教えてください! プログラミングの問題です! お願いします! 出力2と全く同じ出力をするように、 2 2022/06/22 23:10
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 malloc関数を使ってください!お願いします! 最 1 2022/07/21 09:28
- その他(自然科学) 科学技術計算の仕事について 2 2023/02/04 18:09
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
<math.h>があるのにsqrtが・...
-
VBAを何回も作り直して、容量が...
-
RPGでプログラムからソースファ...
-
PRO*C コンパイルエラー
-
セミコロンについて
-
C言語でヘッダファイルにグロー...
-
マクロ コンパイルがグレーバック
-
C++コンパイル時に『 C1083: in...
-
VMwareのLinuxでコンパイルでき...
-
outportb関数について
-
1 つ以上の複数回定義されてい...
-
pyc 編集 閲覧
-
Makefile作成時の拡張子.oとは?
-
クリティカルエラー Expressio...
-
VB6とInputManソフトの関係
-
【VC++6.0(MFC)】警告「LINK : ...
-
sys/types.hの必要性について
-
” OS ビルド ” の意味が分か...
-
関数形式マクロ
-
定数式とはどういう意味でしょ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
” OS ビルド ” の意味が分か...
-
VBAを何回も作り直して、容量が...
-
「fatal error C1189」を回避す...
-
C言語でヘッダファイルにグロー...
-
Makefile作成時の拡張子.oとは?
-
エクセルVBAではRound...
-
1 つ以上の複数回定義されてい...
-
コンパイルエラー:ユーザ定義...
-
セミコロンについて
-
ILSpyで、デコンパイルできない。
-
[c++] <pthread.h>がinclude で...
-
クリティカルエラー Expressio...
-
マクロ コンパイルがグレーバック
-
PRO*C コンパイルエラー
-
外部シンボル "_main"は未解決です
-
他のLinuxでも動くa.outの作り方
-
<math.h>があるのにsqrtが・...
-
戻り値について
-
pyc 編集 閲覧
-
C++コンパイル時に『 C1083: in...
おすすめ情報