从英特尔Fortran调用COM?

时间:2012-06-22 23:12:12

标签: fortran com

我正在尝试从我的Fortran应用程序中使用COM。我做COMINITIALIZE后跟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

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

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

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

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

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

现在我并不喜欢这个警告,如果有人能解释警告和两个不同的电话,我会很高兴,我有它的工作,如果我从来没有得到满意的解释,我可能会学会与之共处。

答案 1 :(得分:1)

非装饰接口成员只是函数名称,但它们的地址在编译时是未知的(由于它们是从COM动态导入的,因此无法知道)。链接器将其值设置为0x00000000,这就是您收到此错误的原因,类似于在C中取消引用NULL指针时发生的情况。

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

  

COM成员函数的接口看起来非常类似于接口   一个动态链接库函数,有一个主要的例外。与DLL函数不同,   在程序链接时永远不知道COM成员函数的地址。   您必须在运行时获取指向对象接口的指针,以及a的地址   特定成员函数由此计算。

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

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

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