1

サードパーティの DLL からいくつかのサブルーチンにアクセスしたいと考えています。関数は、呼び出し規約として STDCALL を使用します。

実行dumpbin /export foo.dllすると、次のような結果が得られます。

      ...
      7    6 00004B40 Foo@16
      ...

以下を使用してコードをコンパイルします。

      gfortran test.f90 -o test.exe -Wl,foo.dll

エラーが発生します: undefined reference to '_foo_'(アンダースコアに注意してください)。

-mrtdコンパイルフラグと、グーグルで検索した他のフラグを追加しようとしましたが、すべて役に立ちませんでした。

アンダースコアを追加しないように fortran に指示するにはどうすればよいですか?


編集:少し説明が必要です。

  1. ソースがない既存の DLL があります。
  2. この DLL は、役立つ場合、Visual Basic で記述されています。
  3. この DLLをfortran から呼び出したい。
  4. test.f90 に書いたら:リンケージエラーFoo(1.0d0)が出るundefined reference to '_foo_'
4

4 に答える 4

5

-fno-underscoring を試しましたか?

http://www.rhinocerus.net/forum/lang-fortran/604847-fortran-dll-call-excel-2.html (末尾近く) で、Tobias Burnus (gfortran 開発者) による投稿を見つけました。 -mrtd の代わりにコンパイラ ディレクティブを使用することをお勧めします。

于 2009-12-31T16:50:44.933 に答える
3

ISO_C_BINDING の使用をコンパイラ属性と組み合わせる必要があります。gfortran マニュアルのMixed-Language Programmingセクションを実際に読む必要があります。他のコンパイラでも使用できる適切なアドバイスを提供します。特に、あなたの場合、stdcall属性が必要です:

interface VisBasSubs

   subroutine foo (DoubleArg)  bind (C, name="Foo")
      !GCC$ ATTRIBUTES stdcall :: foo
      use iso_c_binding, only: c_double
      real (kind=c_double), intent (inout) :: DoubleArg      

   end subroutine foo

end interface VisBasSubs

の行に注意してstdcallください。それが機能するはずです。

于 2010-01-16T14:22:02.307 に答える
1

MSB の -fno-underscoring answerを拡張したかっただけです: f2c & g77 を使用している場合、問題が発生する可能性があります。gfortran のドキュメントから:

-funderscoring が有効な場合、GNU Fortran は、アンダースコアのない外部名に 1 つのアンダースコアを追加します。これは、多くの UNIX Fortran コンパイラによって生成されるコードとの互換性を確保するために行われます。

注意: GNU Fortran のデフォルトの動作は、f2c および g77 と互換性がありません。GNU Fortran でコンパイルされたオブジェクト ファイルが、これらのツールで作成されたオブジェクト コードと互換性を持つようにする場合は、-ff2c オプションを使用してください。

-fno-underscoring の使用は、GNU Fortran を既存のシステム環境に (既存のライブラリやツールなどに対して) 統合するなどの問題を試している場合を除き、お勧めしません。

-fno-underscoringDLLからアンダースコアを削除するなどして、DLL を再コンパイルする必要がある場合があります。

特定の Fortran コンパイラによるアンダースコアの接頭辞/接尾辞に関連する移植性の問題に遭遇しました。一部のコンパイラはデフォルトで _prefix または suffix_ を使用しますが、他のコンパイラはそうではありません! 私の解決策は、プリプロセッサ ディレクティブです。

#ifdef LC_UNSC
#define  GET_DIP_MOMENT get_dip_moment_
#elif LC_NOUNSC
#define  GET_DIP_MOMENT get_dip_moment
#endif
...
     call GET_DIP_MOMENT()
于 2009-12-31T17:21:24.713 に答える
0

別のアプローチは、Fortran2003のISOCバインディングを使用することです。これは、gfortran>=4.3でサポートされています。これにより、Fortranコンパイラの規則ではなく、Cの強調規則(つまり、おそらくなし)が自動的に使用されます。また、Windowsリンカが気にする場合は、サブルーチン名の大文字と小文字(大文字)を制御できます。Fortranは大文字と小文字を区別しないため、どのような場合でもFortranサブルーチンを呼び出すことができます。おそらく、リンカーは小文字に変換しています。

「Foo」を呼び出すFortranルーチンの宣言に次の「インターフェース」を含めると、Fooはdouble型の単一引数(Fortran入出力、またはCのポインター)を持つCサブルーチン(void関数)であると記述されます。 Fooには他のプロパティがあり、インターフェイスを変更する必要があります。「bind」句は、リンカに提供する大文字と小文字を区別する名前を指定します。複数のFortranルーチンからFooを呼び出す場合は、インターフェースをモジュールに入れて、各Fortranルーチンから「使用」するのが最善です。

これはCを対象としています。おそらくVisualBasicでも機能します。ISO Cバインディングは多くの制御を提供するため、これが機能しない場合は、いくつかのバリエーションが機能する可能性があります。

interface VisBasSubs

   subroutine foo (DoubleArg)  bind (C, name="Foo")

      use iso_c_binding, only: c_double
      real (kind=c_double), intent (inout) :: DoubleArg      

   end subroutine foo

end interface VisBasSubs
于 2010-01-03T22:46:06.307 に答える