php - Método de objeto COM no definido
windows delphi (1)
Estoy teniendo problemas para llamar a cualquier método dentro de una clase COM en PHP. Para encontrar todos los métodos dentro de esa clase, utilicé:
$com = new COM(''Some.Class.Name'');
com_print_typeinfo($com);
Viene esta clase contiene unos 100 métodos diferentes. Pero al llamar a alguno de ellos:
$com->SomeMethod();
, aparece este error:
Error grave: llamada a un método no definido com :: SomeMethod () en C: / xampp / htdocs / www / test.php en la línea 22
Esto no sucede cuando uso otros objetos COM, como la clase '' InternetExplorer.Application ''. Además, sé que este objeto COM funciona como se espera con otros lenguajes de programación como Delphi.
Estoy usando PHP 5.5.19, en Windows Vista de 64 bits, y XAMPP, con arquitectura PHP de 32 bits.
Apreciaría cualquier pista sobre lo que pueda estar ocurriendo o alguna posible solución a esta situación.
EDITAR: La aplicación del servidor COM se hace con Delphi.
Esta podría ser otra pista: cuando uso el código
$com = new COM(''Some.Class.Name'');
foreach ($com as $obj) {
echo $obj->Name . "<br />";
}
Yo obtengo:
Error grave: Excepción no detectada ''Excepción'' con mensaje ''El objeto de tipo com no creó un iterador''
Supongo que esto indica que podría haber un problema con la interfaz de la aplicación en sí, pero no sé cuál podría ser ese problema. Trabajo en PHP, por lo que las partes internas de los objetos COM son un borrón total para mí. Pero agradecería mucho cualquier pista sobre los pasos concretos para solucionar esta situación.
EDIT2: Este es el código corto del archivo 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.
Y el problema es (desde el punto de vista de PHP): puedo inicializar el objeto COM con $com = new COM(''The.Class.Name'');
o con $com = new COM(''{GUID}'');
y obtengo la información de tipo con com_print_typeinfo($com);
, así puedo ver que el objeto debería tener los métodos FuncName1()
, FuncName2()
y FuncName3()
, pero cuando intento llamar a cualquiera de ellos con $com->FuncName1(param1, param2);
, lo que devuelve es este error:
Error grave: llamada a un método no definido com :: SomeMethod () en C: / xampp / htdocs / www / test.php en la línea 22
Muchas cosas pueden ir mal con COM, pero trataré de ayudar lo mejor que pueda. Sé que usa términos para describir el problema, como llamar a $ com-> SomeMethod (), pero debe ser más específico en este caso.
COM expone sus clases y funcionalidad a través de dos interfaces básicas: IUnknown y IDispatch.
También tiene una estructura DLL de tipo C, para exponer funciones (no métodos o clases) al mundo "fuera de juego".
Los idiomas que se pueden vincular directamente a una DLL, al leer la tabla de exportación (como Delphi), realizan sus llamadas directamente en la interfaz expuesta por el COM (mediante la interfaz IUnknown).
Los lenguajes de script (como javascript, PHP python, etc.) no pueden llamar directamente en la interfaz. En su lugar, utilizan la interfaz IDispatch.
Esta interfaz sirve como un proxy que expone toda la funcionalidad COM a través de texto simple.
La interfaz IDispatch define métodos estándar para:
1. Consultar un COM en las interfaces que expone.
2. Los nombres de los métodos de un objeto.
3. Los parámetros para cada método.
En tu publicación, despliegas que IDispatch expone tres métodos:
1. FuncName1
2. FuncName2
3. FuncName3
Por lo tanto, no puede llamar a SomeMethod en ISrvObject porque no está expuesto a través de la interfaz IDispatch.
NOTA: COM usa el texto WideString (UTF-16) cuando expone su interfaz. Téngalo en cuenta una vez que haga una llamada en los métodos de interfaz.