未定义的 COM 对象方法

2022-08-30 22:28:52

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

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

这个类包含大约100种不同的方法。但是,当呼叫其中任何一个时:

$com->SomeMethod();

,弹出此错误:

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

当我使用其他COM对象(如“InternetExplorer.Application”类)时,不会发生这种情况。另外,我知道这个COM对象可以按预期与其他编程语言(如Delphi)一起使用。

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

我将不胜感激任何关于可能发生的事情或这种情况的一些可能的解决方法的线索。

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

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

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

我得到:

致命错误:未捕获的异常“异常”,并显示消息“com 类型的对象未创建迭代器”

我想这表明应用程序接口本身可能存在问题,但我不知道这个问题可能是什么。我在PHP中工作,所以COM对象的内部对我来说完全是模糊的。但是,我非常希望得到任何关于为解决这一局势而采取的具体步骤的线索。

编辑2:这是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对象,并且我得到的类型信息,所以我可以看到对象应该有方法,并且,但是当我尝试调用它们中的任何一个时,它返回的是这个错误:$com = new COM('The.Class.Name');$com = new COM('{GUID}');com_print_typeinfo($com);FuncName1()FuncName2()FuncName3()$com->FuncName1(param1, param2);

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


答案 1

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

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

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

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

因此,您无法在 ISrvObject 上调用 SomeMethod,因为它不是通过 IDispatch 接口公开的。
注意:COM 在公开其界面时使用宽字符串 (UTF-16) 文本。在对接口方法进行调用后,请考虑这一点。


答案 2

推荐