【问题标题】:COM object method undefinedCOM 对象方法未定义
【发布时间】:2016-01-30 22:40:38
【问题描述】:

我在 php 中调用 COM 类中的任何方法时遇到问题。为了找到该类中的所有方法,我使用了:

$com = new COM('Some.Class.Name');
com_print_typeinfo($com);

这个类包含大约 100 种不同的方法。但是当调用它们中的任何一个时:

$com->SomeMethod();

,弹出这个错误:

致命错误:调用未定义的方法 com::SomeMethod() C:\xampp\htdocs\www\test.php 第 22 行

当我使用其他 COM 对象时不会发生这种情况,例如 'InternetExplorer.Application' 类。 另外,我知道这个 COM 对象可以与 Delphi 等其他编程语言一起正常工作。

我在 64 位 Windows Vista 和 XAMPP 上使用 PHP 5.5.19,以及 32 位 PHP 架构。

对于可能发生的事情或解决这种情况的一些可能的解决方法,我将不胜感激。

编辑: COM 服务器应用程序是用 Delphi 制作的。

这可能是另一个线索:当我使用代码时

$com = new COM('Some.Class.Name');
foreach ($com as $obj) { 
    echo $obj->Name . "<br />"; 
} 

我明白了:

致命错误:未捕获的异常 'Exception' 带有消息 'Object of type com 没有创建 Iterator'

我猜这表明应用程序界面本身可能存在问题,但我不知道问题可能是什么。我在 PHP 中工作,所以 COM 对象的内部对我来说完全是模糊的。但我非常感谢有关解决这种情况的具体步骤的任何线索。

EDIT2: 这是 Srv_TLB.pas 文件中的简而言之代码。

unit Srv_TLB;

{$TYPEDADDRESS OFF}
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
interface

uses Windows, ActiveX, Classes, Graphics, StdVCL, Variants;

const
  // TypeLibrary Major and minor versions
  SrvMajorVersion = 1;
  SrvMinorVersion = 0;

  LIBID_Srv: TGUID = '{xxxxx-xxx-xxx-xx...}';

  IID_ISrvObject: TGUID = '{yyyyy-yyy-yyy-yy..}';
  CLASS_SrvObject: TGUID = '{zzzzz-zzz-zzz-z...}';
type

// *********************************************************************//
// Forward declaration of types defined in TypeLibrary                    
// *********************************************************************//
  ISrvObject = interface;
  ISrvObjectDisp = dispinterface;

// *********************************************************************//
// Declaration of CoClasses defined in Type Library                       
// (NOTE: Here we map each CoClass to its Default Interface)              
// *********************************************************************//
  SrvObject = ISrvObject;

  ISrvObject = interface(IDispatch)
    ['{yyyyy-yyy-yyy-yy..}']
    function FuncName1(const param1: WideString; const param2: WideString): Integer; safecall;
    function FuncName2: OleVariant; safecall;
    function FuncName3(const param: WideString): Integer; safecall;
  end;

    // *********************************************************************//
// DispIntf:  ISrvObjectDisp
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {yyyyy-yyy-yyy-yy..}
// *********************************************************************//
  ISrvObjectDisp = dispinterface
    ['{yyyyy-yyy-yyy-yy..}']
    function FuncName1(const param1: WideString; const param2: WideString): Integer; dispid 3;
    function FuncName2: OleVariant; dispid 4;
    function FuncName3(const param: WideString): Integer; dispid 5;
  end;

    CoSrvObject = class
    class function Create: ISrvObject;
    class function CreateRemote(const MachineName: string): ISrvObject;
  end;

implementation

uses ComObj;

class function CoSrvObject.Create: ISrvObject;
begin
  Result := CreateComObject(CLASS_SrvObject) as ISrvObject;
end;

class function CoSrvObject.CreateRemote(const MachineName: string): ISrvObject;
begin
  Result := CreateRemoteComObject(MachineName, CLASS_SrvObject) as ISrvObject;
end;

end.

问题是(从 PHP 方面): 我可以使用$com = new COM('The.Class.Name');$com = new COM('{GUID}'); 初始化COM 对象,并使用com_print_typeinfo($com); 获取类型信息,因此我可以看到该对象应该具有FuncName1()FuncName2()FuncName3() 方法,但是当我尝试用$com-&gt;FuncName1(param1, param2); 调用它们中的任何一个时,它返回的是这个错误:

致命错误:调用未定义的方法 com::SomeMethod() C:\xampp\htdocs\www\test.php 第 22 行

【问题讨论】:

  • 在系统上正确注册了吗?我会看看如何找到 DLL 并使用 regsvr32 nameof.dll 注册它,或者如果它是进程外 EXE,则使用 nameof.exe /regserver 运行 EXE
  • @MichaelPetch 谢谢。是的,它是一个.exe。我按照你的建议做了。还是一样。
  • 忘了说我的系统是x64的,.exe文件是为x32编译的,不知道这是否有区别。
  • 您使用的是 64 位版本的 PHP 还是 32 位版本的 PHP?
  • phpinfo() : 架构 x86

标签: php windows delphi com


【解决方案1】:

COM 可能会出现很多问题,但我会尽我所能提供帮助。 我知道您使用术语来描述问题,例如调用 $com->SomeMethod(),但在这种情况下您需要更具体。

COM 通过两个基本接口 IUnknown 和 IDispatch 公开其类和功能。
它还有一个 C 类型的 DLL 结构,用于将函数(不是方法或类)暴露给“外部”世界。
可以直接链接到 DLL 的语言,通过读取导出表(如 Delphi),直接在 COM 公开的接口上进行调用(使用 IUnknown 接口)。

脚本语言(如 javascript、PHP python 等)不能直接在界面上调用。相反,他们使用 IDispatch 接口。
此接口充当代理,通过简单的文本公开所有 COM 功能。
IDispatch 接口定义标准方法:
1. 在它暴露的接口上查询一个 COM
2. 对象的方法名。
3. 每种方法的参数。

在您的帖子中,您显示 IDispatch 公开了三种方法:
1. FuncName1
2. FuncName2
3. FuncName3

因此,您不能在 ISrvObject 上调用 SomeMethod,因为它没有通过 IDispatch 接口公开。
注意: COM 在公开其接口时使用 WideString (UTF-16) 文本。调用接口方法后,请考虑到这一点。

【讨论】:

  • SomeMethod 作为给定三个 Iment 中的任何一个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-05
  • 2011-08-15
  • 2016-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多