Подтвердить что ты не робот

Метод COM-объекта undefined

У меня возникают проблемы с вызовом любого метода внутри COM-класса в php. Чтобы найти все методы внутри этого класса, я использовал:

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

Выходит, этот класс содержит около 100 различных методов. Но при вызове любого из них:

$com->SomeMethod();

эта ошибка появляется:

Неустранимая ошибка: вызов метода undefined com:: SomeMethod() в C:\xampp\htdocs\www\test.php в строке 22

Этого не происходит, когда я использую другие COM-объекты, например класс InternetExplorer.Application. Кроме того, я знаю, что этот COM-объект работает так, как ожидалось, с другими языками программирования, такими как Delphi.

Я использую PHP 5.5.19, на 64-битной Windows Vista и XAMPP, с 32-битной архитектурой PHP.

Буду признателен за то, что может произойти, или какое-то возможное обходное решение этой ситуации.

EDIT: Приложение COM-сервера выполнено с помощью Delphi.

Это может быть другой ключ: когда я использую код

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

Я получаю:

Неустранимая ошибка: исключить исключение "Исключение" с сообщением "Объект тип 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-объект с помощью $com = new COM('The.Class.Name'); или $com = new COM('{GUID}');, и я получаю информацию о типе с com_print_typeinfo($com);, поэтому я вижу, что объект должен иметь методы FuncName1(), FuncName2() и FuncName3(), но когда я пытаюсь вызвать любой из них с помощью $com->FuncName1(param1, param2);, то, что он возвращает, является эта ошибка:

Неустранимая ошибка: вызов метода undefined com:: SomeMethod() в C:\xampp\htdocs\www\test.php в строке 22

4b9b3361

Ответ 1

Многие вещи могут пойти не так с COM, но я постараюсь помочь как можно лучше. Я знаю, что вы используете термины для описания проблемы, например вызов $com- > SomeMethod(), но в этом случае вам нужно быть более конкретным.

COM предоставляет свои классы и функции через два основных интерфейса IUnknown и IDispatch.
Он также имеет DLL-структуру типа C, чтобы выставлять функции (не методы или классы) в мир "вне стороны".
Языки, которые могут ссылаться непосредственно на DLL, путем чтения таблицы экспорта (например, Delphi), делают свои вызовы непосредственно на интерфейсе, открытом COM (используя интерфейс IUnknown).

Языки Script (например, javascript, PHP python и т.д.) не могут напрямую обращаться к интерфейсу. Вместо этого они используют интерфейс IDispatch.
Этот интерфейс служит прокси-сервером, который предоставляет все функции COM через простой текст.
Интерфейс IDispatch определяет стандартные методы для:
 1. запрос COM на интерфейсах, которые он предоставляет
 2. Имена методов объекта.
 3. Параметры для каждого метода.

В вашем сообщении вы показываете, что IDispatch обнаружил три метода:
 1. FuncName1
 2. FuncName2
 3. FuncName3

Поэтому вы не можете вызвать SomeMethod в ISrvObject, потому что он не отображается через интерфейс IDispatch.
ПРИМЕЧАНИЕ. COM использует текст WideString (UTF-16) при экспонировании его интерфейса. Учитывайте это, когда вы делаете вызов методам интерфейса.