18

I'm having troubles calling any method inside a COM class in php. In order to find all methods inside that class, I used:

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

Comes out this class contains some 100 different methods. But when calling any of them:

$com->SomeMethod();

,this error pops up:

Fatal error: Call to undefined method com::SomeMethod() in C:\xampp\htdocs\www\test.php on line 22

This doesn't happen when I use other COM objects, like 'InternetExplorer.Application' class. Also, I know this COM object works as expected with other programming languages like Delphi.

I'm using PHP 5.5.19, on 64-bit Windows Vista, and XAMPP, with 32-bit PHP architecture.

I would appreciate any lead on what may be going on or some possible workaround to this situation.

EDIT: The COM server application is made with Delphi.

This might be another clue: When I use the code

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

I get:

Fatal error: Uncaught exception 'Exception' with message 'Object of type com did not create an Iterator'

I guess this indicates there could be a problem with the application interface itself, but I don't know what that problem might be. I work in PHP, so the insides of COM objects are a total blur to me. But I would very much appreciate any clue on the concrete steps in order to fix this situation.

EDIT2: This is the in short code from the Srv_TLB.pas file.

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.

And the problem is (from the PHP side of things): I can initialize the COM object with $com = new COM('The.Class.Name'); or with $com = new COM('{GUID}');, and I get the type info with com_print_typeinfo($com);, so I can see the object should have the methods FuncName1(), FuncName2() and FuncName3(), but when I try to call any of them with $com->FuncName1(param1, param2);, what it returns is this error:

Fatal error: Call to undefined method com::SomeMethod() in C:\xampp\htdocs\www\test.php on line 22

26
  • 1
    Is it properly registered on the system? I'd see about finding the DLL and register it with regsvr32 nameof.dll or if it is out-of-proc EXE run the EXE with nameof.exe /regserver Commented Oct 30, 2015 at 14:33
  • @MichaelPetch thank you. Yes it's an .exe. I did what you suggested. Still the same. Commented Oct 30, 2015 at 14:57
  • Forgot to mention My system is on x64, and the .exe file is compiled for x32, not sure if that makes a difference. Commented Nov 2, 2015 at 8:10
  • Are you using a 64-bit version of PHP or 32-bit version of PHP? Commented Nov 2, 2015 at 18:18
  • phpinfo() : Architecture x86 Commented Nov 3, 2015 at 8:00

1 Answer 1

1

Many things can go wrong with COM but I will try to help as best I can. I know that you use terms to describe the issue, like calling $com->SomeMethod(), but you need to be more specific in this case.

COM exposes its classes and functionality through two basic interfaces IUnknown and IDispatch.
It also has a DLL structure of C type, to expose functions (Not methods or classes) to the "out side" world.
Languages that can link directly to a DLL's, by reading the export table (like Delphi), make their calls directly on the interface exposed by the COM (Using IUnknown interface).

Script languages (like javascript, PHP python etc.) cannot call directly on the interface. Instead they use IDispatch interface.
This interface serve as a proxy that expose all COM functionality through simple text.
The IDispatch interface define standard methods for:
1. querying a COM on the interfaces it exposes
2. The methods' names of an object.
3. The parameters for each method.

In your post you display that IDispatch exposed three methods:
1. FuncName1
2. FuncName2
3. FuncName3

Therefore you cannot call SomeMethod on ISrvObject because it is not exposed via the IDispatch interface.
NOTE: COM uses WideString (UTF-16) text when exposing its interface. Take that into account once you do make a call on the interface methods.

Sign up to request clarification or add additional context in comments.

1 Comment

SomeMethod as any of the given three I ment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.