2

我试图让 COM 从我的 Fortran 应用程序中工作。我做 aCOMINITIALIZE后跟 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 动态导入的,所以无法知道)。链接器将它们的值设置为0x00000000,这就是为什么会出现此错误,类似于NULL在 C 中取消引用指针时发生的情况。

正如 Compaq Visual Fortran 用户指南中所写:

COM 成员函数的接口看起来与动态链接库函数的接口非常相似,但有一个主要例外。与 DLL 函数不同,COM 成员函数的地址在程序链接时永远是未知的。您必须在运行时获得指向对象接口的指针,并从中计算特定成员函数的地址。

这正是装饰版本所做的。它们$OBJECT实际上是指向对象接口的指针,而后者又是实现接口的实际对象方法的地址表(vtable)。然后,修饰函数在实际方法的 vtable 中添加偏移量,并通过指针分配结果地址,然后才调用非修饰函数(不再是NULL指针)。

请参阅此处提供的 Compaq Visual Fortran 用户指南的第 541 页(调用模块向导生成的例程) 。有一个带注释的示例说明究竟生成了什么以及为什么生成。注意接口定义的注释 6(声明了指向非修饰接口成员的指针)和修饰函数的注释 4。

警告与来自 Microsoft 链接器的警告 LNK4217#11077相同。可能忽略它是安全的。

于 2012-06-25T09:29:30.500 回答
1

好的,看起来这是一个特定于包的问题。更准确地说,这是我对软件包或当前 Fortran 约定的误解。据我所知,包中的几乎所有方法都定义了两次,一次使用常规名称,一次使用$前言。

因此,如果我使用$IMyOlePkg_GetPackageVersion调用而不是IMyOlePkg_GetPackageVersion调用,我会收到构建警告:

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

但它有效!特别有趣的是,该$方法看起来只是添加一个偏移量,然后调用该non-$方法。

现在虽然我真的不喜欢这个警告,如果有人能解释警告和两个不同的电话,我会很高兴,但我有它的工作,如果我从来没有得到令人满意的解释,我可能会学会生活接着就,随即。

于 2012-06-24T05:26:13.597 回答