2

Fortran アプリケーションから COM を動作させようとしています。a のCOMINITIALIZE後に aを実行しCOMCreateObjectByProgIDます。これらは両方とも成功したように見え、ゼロのステータスを返します。ただし、COM オブジェクトを使用しようとすると、次のようになります。

Unhandled exception at 0x00000000 in FortranProg01.exe: 0xC0000005: Access violation.

このエラーはほとんどすべてのことを意味する可能性があることは理解していますが、この問題を引き起こす COM の一般的な問題について何か提案をした人はいますか? 私のプログラムコード:

program FortranProg01

use myolepg
implicit none

integer*4 comInitStatus
integer:: comCreateStatus
INTEGER(INT_PTR_KIND()) $OBJECT
INTEGER(4) funcResult
REAL(8) pkgVersion

call COMINITIALIZE(comInitStatus)
print *, comInitStatus

call COMCreateObjectByProgID('MyOlePg.MyOlePkg', $OBJECT, comCreateStatus)
print *, comCreateStatus

funcResult = IMyOlePkg_GetPackageVersion($OBJECT, pkgVersion)
print *, funcResult

call COMUNINITIALIZE()

end program FortranProg01

ウィザードで生成されたインターフェイス コード:

INTERFACE

  !property PackageVersion

    INTEGER(4) FUNCTION IMyOlePkg_GetPackageVersion($OBJECT, pVal)

    INTEGER(INT_PTR_KIND()), INTENT(IN) :: $OBJECT ! Object Pointer

    !DEC$ ATTRIBUTES VALUE :: $OBJECT

    REAL(8), INTENT(OUT) :: pVal 

    !DEC$ ATTRIBUTES REFERENCE :: pVal

  !DEC$ ATTRIBUTES STDCALL :: IMyOlePkg_GetPackageVersion

  END FUNCTION IMyOlePkg_GetPackageVersion

END INTERFACE

どんな助けでも大歓迎です!

4

2 に答える 2

1

装飾されていないインターフェイス メンバーは単なる関数名ですが、それらのアドレスはコンパイル時にわかりません (COM から動的にインポートされるため、わかりません)。リンカーはそれらの値をに設定するため、C でポインターを0x00000000逆参照するときに発生するのと同様に、このエラーが発生します。NULL

Compaq Visual Fortran ユーザー ガイドには次のように書かれています。

COM メンバー関数のインターフェイスは、ダイナミック リンク ライブラリ関数のインターフェイスとよく似ていますが、1 つの大きな例外があります。DLL 関数とは異なり、COM メンバー関数のアドレスは、プログラムのリンク時にわかりません。実行時にオブジェクトのインターフェイスへのポインターを取得する必要があり、特定のメンバー関数のアドレスはそこから計算されます。

これはまさに装飾されたバージョンが行うことです。どちらが実際に$OBJECTはオブジェクト インターフェイスへのポインタであり、これはインターフェイスを実装する実際のオブジェクト メソッドへのアドレスのテーブル (vtable) です。装飾された関数は、実際のメソッドの vtable にオフセットを追加し、ポインターを介して結果のアドレスを割り当ててから、装飾されていないもの (ポインターではなくなります)NULL呼び出します。

ここから入手できる Compaq Visual Fortran ユーザー ガイドの541 ページ (モジュール ウィザードによって生成されたルーチンの呼び出し) を参照してください。正確に生成されるものとその理由の注釈付きの例があります。インターフェイス定義の注釈 6 (装飾されていないインターフェイス メンバーへのポインターが宣言されています) と、装飾された関数の注釈 4 に注意してください。

警告は、 Microsoft のリンカーからの警告 LNK4217#11077と同じです。おそらく、無視しても問題ありません。

于 2012-06-25T09:29:30.500 に答える
1

OK、これはパッケージ固有の問題だったようです。より正確には、パッケージまたは現在の Fortran 規則のいずれかについての私の誤解でした。私が知る限り、パッケージ内のほぼすべてのメソッドは 2 回定義されています。1 回は通常の名前で、もう 1 回は$序文で定義されています。

したがって、$IMyOlePkg_GetPackageVersion呼び出しの代わりに呼び出しを使用するとIMyOlePkg_GetPackageVersion、ビルド警告が表示されます。

ipo: warning #11077: ...: locally defined symbol ... imported

しかし、それは動作します!特に興味深いのは、$メソッドが単にオフセットを追加してからメソッドを呼び出しているように見えることnon-$です。

今、私は警告があまり好きではありません.誰かが警告と2つの異なる呼び出しの両方を説明できれば幸いです.それと。

于 2012-06-24T05:26:13.597 に答える