Windows 7 64 ビットで R 内で使用するために、Absoft Pro Fortran 13.0.3、64 ビットで Fortran DLL を構築しようとしています。
これが私のファイル mycalc.f です (機能をテストするためだけのばかげた例です):
subroutine mycalcf(a,b,c)
real*8 a,b,c
dll_export mycalcf
c=a+b*b
end
このステートメントdll_export
は標準ではありませんが、一部の Fortran コンパイラに含まれています (私の知る限り、Lahey と CVF にもあり、Intel Fortran には代わりにコンパイラ ディレクティブがあります)。どのシンボルをエクスポートするかをコンパイラに伝えるだけです。
私は正常にコンパイルします:
af90 -m64 -dll -YDLL_NAMES=LCS mycalc.f -o mycalc.dll
このオプション-YDLL_NAMES=LCS
は、小文字の記号を使用してライブラリを構築するようにコンパイラに指示します。これは、R に適しているようです。
を実行するdumpbin /exports mycalc.dll
と、エクスポートされたシンボルで mycalcf を小文字で、前後にアンダースコアなしで見つけることができます。
現在、R (64 ビット版) からは、次のように動作します。
dyn.load("mycalc.dll")
is.loaded("mycalcf")
.Fortran("mycalcf", a=4, b=5, c=0)
期待どおり、リターン時に c=29 を取得します。
しかし、R を再起動すると、以下は機能しません (is.loaded
テストを削除しただけであることに注意してください)。
dyn.load("mycalc.dll")
.Fortran("mycalcf", a=4, b=5, c=0)
エラーが表示されます: Fortran symbol name "mycalcf" not in load table
。
ここで私の質問は、なぜこのテストがそれほど重要なのですか?
比較のために、Absoft の代わりに gfortran で同じことを試してみると、まったく問題ありません。私はコンパイルします:gfortran -m64 -shared -o mycalc2.dll mycalc.f
(gfortranによって必要とされず、認識さえされないdll_exportステートメントをコメントアウトした後)。次にRで:
dyn.load("mycalc2.dll")
.Fortran("mycalcf", a=4, b=5, c=0)
そして、c=29 を取得します。エラーはありません。
ここで、Absoft リンカ (実際には Microsoft の link.exe) によって自動的に行われない gcc リンカの動作があると思われます。しかし、それが何であるかについてのヒントはありません。
どんなアイデアでも大歓迎です!
わかりました、Vladimir F からの良い質問の後の解決策 (コメントを参照)。実際には、シンボル名にアンダースコアを追加する必要があります。コンパイラ オプションでこれを行う方法がないため、CDEC$
ディレクティブが必要です ( HPまたはIntelのドキュメントを参照)。
ここでは簡単です:
subroutine mycalcf(a,b,c)
CDEC$ attributes alias:'mycalcf_' :: mycalcf
real*8 a,b,c
dll_export mycalcf
c=a+b*b
end
Absoftフォーラムからの2番目の解決策:実際、私は最初から間違っていました。私が思っていたのとは反対に、dll_export ステートメントを使用する必要はなく、問題が発生することさえありました。それがないと、コンパイラはアンダースコアを追加します。gfortran のように、すべてのシンボルがデフォルトでエクスポートされます。したがって、正しいコードは次のとおりです。
subroutine mycalcf(a,b,c)
real*8 a,b,c
c=a+b*b
end
小文字の記号を取得するためのオプションは必要ありません。これはデフォルトでもあります。
ただし、1 つの疑問が残ります。R 関数.Fortran
は常にアンダースコアを追加しますか (そうしないように指示する方法はありますか?)。また、常に追加される場合is.loaded
、事前に呼び出されたときに呼び出しが機能するのはなぜですか? R はここで奇妙なことをしているようです。is.loaded
R のソース コード ( まで
を追跡しようとしdo_isloaded
、src\main\dotcode.c
役に立ちませんでした。