summaryrefslogtreecommitdiff
path: root/php/src/php5/Proxy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'php/src/php5/Proxy.cpp')
-rw-r--r--php/src/php5/Proxy.cpp1762
1 files changed, 1762 insertions, 0 deletions
diff --git a/php/src/php5/Proxy.cpp b/php/src/php5/Proxy.cpp
new file mode 100644
index 00000000000..b86c15314c9
--- /dev/null
+++ b/php/src/php5/Proxy.cpp
@@ -0,0 +1,1762 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <Proxy.h>
+#include <Connection.h>
+#include <Endpoint.h>
+#include <Util.h>
+
+using namespace std;
+using namespace IcePHP;
+
+ZEND_EXTERN_MODULE_GLOBALS(ice)
+
+//
+// Here's a brief description of how proxies are handled by this extension.
+//
+// A single PHP class, ObjectPrx, is registered. This is an "internal" class,
+// i.e., implemented by this extension, and it is used to represent all proxies
+// regardless of interface type.
+//
+// Like in C++, a proxy is only capable of invoking the Ice::ObjectPrx operations
+// until it is narrowed with a checked or unchecked cast. Unlike C++, no PHP classes
+// are created for proxies, because all marshaling activity is driven by the type
+// definitions, not by statically-generated code.
+//
+// In order to perform a checked or unchecked cast, the generated code invokes
+// ice_checkedCast or ice_uncheckedCast on the proxy to be narrowed, supplying a scoped
+// name for the desired type. Internally, the proxy validates the scoped name and returns
+// a new proxy containing the class or interface definition. This proxy is considered
+// to be narrowed to that interface and therefore supports user-defined operations.
+//
+// Naturally, there are many predefined proxy methods (e.g., ice_getIdentity, etc.), but
+// the proxy also needs to support user-defined operations (if it has type information).
+// We use a Zend API hook that allows us to intercept the invocation of unknown methods
+// on the proxy object.
+//
+
+//
+// Class entries represent the PHP class implementations we have registered.
+//
+namespace IcePHP
+{
+zend_class_entry* proxyClassEntry = 0;
+}
+
+//
+// Ice::ObjectPrx support.
+//
+static zend_object_handlers _handlers;
+
+extern "C"
+{
+static zend_object_value handleAlloc(zend_class_entry* TSRMLS_DC);
+static void handleFreeStorage(void* TSRMLS_DC);
+static zend_object_value handleClone(zval* TSRMLS_DC);
+#if PHP_VERSION_ID < 50400
+static union _zend_function* handleGetMethod(zval**, char*, int TSRMLS_DC);
+#else
+static union _zend_function* handleGetMethod(zval**, char*, int, const _zend_literal* TSRMLS_DC);
+#endif
+static int handleCompare(zval*, zval* TSRMLS_DC);
+}
+
+static ClassInfoPtr lookupClass(const string& TSRMLS_DC);
+
+namespace IcePHP
+{
+
+//
+// Encapsulates proxy and type information.
+//
+class Proxy : public IceUtil::Shared
+{
+public:
+
+ Proxy(const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC);
+ ~Proxy();
+
+ bool clone(zval*, const Ice::ObjectPrx& TSRMLS_DC);
+ bool cloneUntyped(zval*, const Ice::ObjectPrx& TSRMLS_DC);
+ static bool create(zval*, const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC);
+
+ Ice::ObjectPrx proxy;
+ ClassInfoPtr info;
+ CommunicatorInfoPtr communicator;
+ zval* connection;
+ zval* cachedConnection;
+#if ZTS
+ TSRMLS_D;
+#endif
+};
+typedef IceUtil::Handle<Proxy> ProxyPtr;
+
+} // End of namespace IcePHP
+
+ZEND_METHOD(Ice_ObjectPrx, __construct)
+{
+ runtimeError("proxies cannot be instantiated, use stringToProxy()" TSRMLS_CC);
+}
+
+ZEND_METHOD(Ice_ObjectPrx, __toString)
+{
+ if(ZEND_NUM_ARGS() > 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ string str = _this->proxy->ice_toString();
+ RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getCommunicator)
+{
+ if(ZEND_NUM_ARGS() > 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ _this->communicator->getZval(return_value TSRMLS_CC);
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_toString)
+{
+ ZEND_MN(Ice_ObjectPrx___toString)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getIdentity)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ createIdentity(return_value, _this->proxy->ice_getIdentity() TSRMLS_CC);
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_identity)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ zend_class_entry* cls = idToClass("::Ice::Identity" TSRMLS_CC);
+ assert(cls);
+
+ zval *zid;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zid, cls) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ Ice::Identity id;
+ if(extractIdentity(zid, id TSRMLS_CC))
+ {
+ try
+ {
+ if(!_this->cloneUntyped(return_value, _this->proxy->ice_identity(id) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getContext)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ if(!createStringMap(return_value, _this->proxy->ice_getContext() TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_context)
+{
+ zval* arr = 0;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("a"), &arr) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ //
+ // Populate the context.
+ //
+ Ice::Context ctx;
+ if(arr && !extractStringMap(arr, ctx TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_context(ctx) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getFacet)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ string facet = _this->proxy->ice_getFacet();
+ ZVAL_STRINGL(return_value, STRCAST(facet.c_str()), static_cast<int>(facet.length()), 1);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_facet)
+{
+ char* name;
+ int len;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &name, &len) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ if(!_this->cloneUntyped(return_value, _this->proxy->ice_facet(name) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getAdapterId)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ string id = _this->proxy->ice_getAdapterId();
+ ZVAL_STRINGL(return_value, STRCAST(id.c_str()), static_cast<int>(id.length()), 1);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_adapterId)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ char* id;
+ int len;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &id, &len) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_adapterId(id) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getEndpoints)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ Ice::EndpointSeq endpoints = _this->proxy->ice_getEndpoints();
+
+ array_init(return_value);
+ uint idx = 0;
+ for(Ice::EndpointSeq::const_iterator p = endpoints.begin(); p != endpoints.end(); ++p, ++idx)
+ {
+ zval* elem;
+ MAKE_STD_ZVAL(elem);
+ if(!createEndpoint(elem, *p TSRMLS_CC))
+ {
+ zval_ptr_dtor(&elem);
+ RETURN_NULL();
+ }
+ add_index_zval(return_value, idx, elem);
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_endpoints)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ zval* zv;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("a"), &zv) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ Ice::EndpointSeq seq;
+
+ HashTable* arr = Z_ARRVAL_P(zv);
+ HashPosition pos;
+ void* data;
+
+ zend_hash_internal_pointer_reset_ex(arr, &pos);
+ while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
+ {
+ zval** val = reinterpret_cast<zval**>(data);
+
+ if(Z_TYPE_PP(val) != IS_OBJECT)
+ {
+ runtimeError("expected an element of type Ice::Endpoint" TSRMLS_CC);
+ RETURN_NULL();
+ }
+
+ Ice::EndpointPtr endpoint;
+ if(!fetchEndpoint(*val, endpoint TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+
+ seq.push_back(endpoint);
+
+ zend_hash_move_forward_ex(arr, &pos);
+ }
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_endpoints(seq) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getLocatorCacheTimeout)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ Ice::Int timeout = _this->proxy->ice_getLocatorCacheTimeout();
+ ZVAL_LONG(return_value, static_cast<long>(timeout));
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getConnectionId)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ string connectionId = _this->proxy->ice_getConnectionId();
+ ZVAL_STRINGL(return_value, STRCAST(connectionId.c_str()), static_cast<int>(connectionId.length()), 1);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_locatorCacheTimeout)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ long l;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("l"), &l) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_locatorCacheTimeout(l) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_isConnectionCached)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ bool b = _this->proxy->ice_isConnectionCached();
+ ZVAL_BOOL(return_value, b ? 1 : 0);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_connectionCached)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ zend_bool b;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("b"), &b) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_connectionCached(b ? true : false) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getEndpointSelection)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ Ice::EndpointSelectionType type = _this->proxy->ice_getEndpointSelection();
+ ZVAL_LONG(return_value, type == Ice::Random ? 0 : 1);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_endpointSelection)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ long l;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("l"), &l) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
+
+ if(l < 0 || l > 1)
+ {
+ runtimeError("expecting Random or Ordered" TSRMLS_CC);
+ RETURN_NULL();
+ }
+
+ try
+ {
+ Ice::EndpointSelectionType type = l == 0 ? Ice::Random : Ice::Ordered;
+ if(!_this->clone(return_value, _this->proxy->ice_endpointSelection(type) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_isSecure)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ bool b = _this->proxy->ice_isSecure();
+ RETURN_BOOL(b ? 1 : 0);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_FALSE;
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_secure)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ zend_bool b;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("b"), &b TSRMLS_CC) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_secure(b ? true : false) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getEncodingVersion)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ if(!createEncodingVersion(return_value, _this->proxy->ice_getEncodingVersion() TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_encodingVersion)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ zend_class_entry* cls = idToClass("::Ice::EncodingVersion" TSRMLS_CC);
+ assert(cls);
+
+ zval *zv;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, cls) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ Ice::EncodingVersion v;
+ if(extractEncodingVersion(zv, v TSRMLS_CC))
+ {
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_encodingVersion(v) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_isPreferSecure)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ bool b = _this->proxy->ice_isPreferSecure();
+ RETURN_BOOL(b ? 1 : 0);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_FALSE;
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_preferSecure)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ zend_bool b;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("b"), &b TSRMLS_CC) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_preferSecure(b ? true : false) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getRouter)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ Ice::RouterPrx router = _this->proxy->ice_getRouter();
+ if(router)
+ {
+ ClassInfoPtr info = lookupClass("::Ice::Router" TSRMLS_CC);
+ if(!info)
+ {
+ RETURN_NULL();
+ }
+
+ assert(info);
+
+ if(!createProxy(return_value, router, info, _this->communicator TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ else
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_FALSE;
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_router)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ zval* zprx;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O!"), &zprx, proxyClassEntry TSRMLS_CC) !=
+ SUCCESS)
+ {
+ RETURN_NULL();
+ }
+
+ Ice::ObjectPrx proxy;
+ ClassInfoPtr def;
+ if(zprx && !fetchProxy(zprx, proxy, def TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+
+ Ice::RouterPrx router;
+ if(proxy)
+ {
+ if(!def || !def->isA("::Ice::Router"))
+ {
+ runtimeError("ice_router requires a proxy narrowed to Ice::Router" TSRMLS_CC);
+ RETURN_NULL();
+ }
+ router = Ice::RouterPrx::uncheckedCast(proxy);
+ }
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_router(router) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getLocator)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ Ice::LocatorPrx locator = _this->proxy->ice_getLocator();
+ if(locator)
+ {
+ ClassInfoPtr info = lookupClass("::Ice::Locator" TSRMLS_CC);
+ if(!info)
+ {
+ RETURN_NULL();
+ }
+
+ if(!createProxy(return_value, locator, info, _this->communicator TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ else
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_FALSE;
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_locator)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ zval* zprx;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O!"), &zprx, proxyClassEntry TSRMLS_CC) !=
+ SUCCESS)
+ {
+ RETURN_NULL();
+ }
+
+ Ice::ObjectPrx proxy;
+ ClassInfoPtr def;
+ if(zprx && !fetchProxy(zprx, proxy, def TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+
+ Ice::LocatorPrx locator;
+ if(proxy)
+ {
+ if(!def || !def->isA("::Ice::Locator"))
+ {
+ runtimeError("ice_locator requires a proxy narrowed to Ice::Locator" TSRMLS_CC);
+ RETURN_NULL();
+ }
+ locator = Ice::LocatorPrx::uncheckedCast(proxy);
+ }
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_locator(locator) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_twoway)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_twoway() TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_isTwoway)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ bool b = _this->proxy->ice_isTwoway();
+ RETURN_BOOL(b ? 1 : 0);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_FALSE;
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_oneway)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_oneway() TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_isOneway)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ bool b = _this->proxy->ice_isOneway();
+ RETURN_BOOL(b ? 1 : 0);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_FALSE;
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_batchOneway)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_batchOneway() TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_isBatchOneway)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ bool b = _this->proxy->ice_isBatchOneway();
+ RETURN_BOOL(b ? 1 : 0);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_FALSE;
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_datagram)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_datagram() TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_isDatagram)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ bool b = _this->proxy->ice_isDatagram();
+ RETURN_BOOL(b ? 1 : 0);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_FALSE;
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_batchDatagram)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_batchDatagram() TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_isBatchDatagram)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ bool b = _this->proxy->ice_isBatchDatagram();
+ RETURN_BOOL(b ? 1 : 0);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_FALSE;
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_compress)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ zend_bool b;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("b"), &b) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
+
+ try
+ {
+ if(!_this->clone(return_value, _this->proxy->ice_compress(b ? true : false) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_timeout)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ long l;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("l"), &l) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
+ // TODO: range check?
+ if(!_this->clone(return_value, _this->proxy->ice_timeout(l) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_connectionId)
+{
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ char* id;
+ int idLen;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &id, &idLen) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
+ if(!_this->clone(return_value, _this->proxy->ice_connectionId(id) TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getConnection)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ Ice::ConnectionPtr con = _this->proxy->ice_getConnection();
+ if(!createConnection(return_value, con TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_getCachedConnection)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ Ice::ConnectionPtr con = _this->proxy->ice_getCachedConnection();
+ if(!con || !createConnection(return_value, con TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_flushBatchRequests)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ _this->proxy->ice_flushBatchRequests();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+}
+
+static ClassInfoPtr
+lookupClass(const string& id TSRMLS_DC)
+{
+ ClassInfoPtr info = getClassInfoById(id TSRMLS_CC);
+ if(!info)
+ {
+ if(!id.empty() && id[id.size() - 1] == '*')
+ {
+ info = getClassInfoById(id.substr(0, id.size() - 1) TSRMLS_CC);
+ }
+ }
+
+ if(info && !info->defined)
+ {
+ runtimeError("%s is declared but not defined" TSRMLS_CC, id.c_str());
+ }
+ else if(!info)
+ {
+ runtimeError("no definition found for class or interface %s" TSRMLS_CC, id.c_str());
+ }
+
+ return info;
+}
+
+static void
+do_cast(INTERNAL_FUNCTION_PARAMETERS, bool check)
+{
+ //
+ // First argument is required and should be a scoped name. The second and third arguments
+ // are optional and represent a facet name, a context, or a facet name followed by a context.
+ //
+ if(ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 3)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ char* id;
+ int idLen;
+ char* facet = 0;
+ int facetLen;
+ zval* arr = 0;
+
+ if(zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s|s!a!"), &id,
+ &idLen, &facet, &facetLen, &arr) == FAILURE)
+ {
+ facet = 0;
+ if(zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s|a!"), &id,
+ &idLen, &arr) == FAILURE)
+ {
+ php_error(E_ERROR, "%s() requires a type id followed by an optional facet and/or context",
+ get_active_function_name(TSRMLS_C));
+ return;
+ }
+ }
+
+ ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ //
+ // Populate the context.
+ //
+ Ice::Context ctx;
+ if(arr && !extractStringMap(arr, ctx TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+
+ try
+ {
+ ClassInfoPtr info = lookupClass(id TSRMLS_CC);
+ if(!info)
+ {
+ RETURN_NULL();
+ }
+
+ Ice::ObjectPrx prx = _this->proxy;
+ if(facet)
+ {
+ prx = prx->ice_facet(facet);
+ }
+
+ if(arr)
+ {
+ prx = prx->ice_context(ctx);
+ }
+
+ if(check)
+ {
+ //
+ // Verify that the object supports the requested type.
+ //
+ if(!prx->ice_isA(info->id))
+ {
+ RETURN_NULL();
+ }
+ }
+
+ if(!createProxy(return_value, prx, info, _this->communicator TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+ }
+ catch(const Ice::FacetNotExistException&)
+ {
+ // Ignore.
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETVAL_FALSE;
+ }
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_uncheckedCast)
+{
+ do_cast(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
+}
+
+ZEND_METHOD(Ice_ObjectPrx, ice_checkedCast)
+{
+ do_cast(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
+}
+
+IcePHP::Proxy::Proxy(const Ice::ObjectPrx& p, const ClassInfoPtr& i, const CommunicatorInfoPtr& comm TSRMLS_DC) :
+ proxy(p), info(i), communicator(comm), connection(0), cachedConnection(0)
+{
+#ifdef ZTS
+ this->TSRMLS_C = TSRMLS_C;
+#endif
+
+ //
+ // We want to ensure that the PHP object corresponding to the communicator is
+ // not destroyed until after this proxy is destroyed.
+ //
+ communicator->addRef(TSRMLS_C);
+}
+
+IcePHP::Proxy::~Proxy()
+{
+ communicator->decRef(TSRMLS_C);
+ if(connection)
+ {
+ zval_ptr_dtor(&connection);
+ }
+ if(cachedConnection)
+ {
+ zval_ptr_dtor(&cachedConnection);
+ }
+}
+
+bool
+IcePHP::Proxy::clone(zval* zv, const Ice::ObjectPrx& p TSRMLS_DC)
+{
+ return create(zv, p, info, communicator TSRMLS_CC);
+}
+
+bool
+IcePHP::Proxy::cloneUntyped(zval* zv, const Ice::ObjectPrx& p TSRMLS_DC)
+{
+ return create(zv, p, 0, communicator TSRMLS_CC);
+}
+
+bool
+IcePHP::Proxy::create(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm
+ TSRMLS_DC)
+{
+ ClassInfoPtr cls = info;
+ if(!cls)
+ {
+ cls = getClassInfoById("::Ice::Object" TSRMLS_CC);
+ assert(cls);
+ }
+
+ if(object_init_ex(zv, proxyClassEntry) != SUCCESS)
+ {
+ runtimeError("unable to initialize proxy" TSRMLS_CC);
+ return false;
+ }
+
+ Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(zv TSRMLS_CC);
+ ProxyPtr proxy = new Proxy(p, cls, comm TSRMLS_CC);
+ assert(!obj->ptr);
+ obj->ptr = new ProxyPtr(proxy);
+
+ return true;
+}
+
+#ifdef _WIN32
+extern "C"
+#endif
+static zend_object_value
+handleAlloc(zend_class_entry* ce TSRMLS_DC)
+{
+ zend_object_value result;
+
+ Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::create(ce TSRMLS_CC);
+ assert(obj);
+
+ result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleFreeStorage,
+ 0 TSRMLS_CC);
+ result.handlers = &_handlers;
+
+ return result;
+}
+
+#ifdef _WIN32
+extern "C"
+#endif
+static void
+handleFreeStorage(void* p TSRMLS_DC)
+{
+ Wrapper<ProxyPtr>* obj = static_cast<Wrapper<ProxyPtr>*>(p);
+ delete obj->ptr;
+ zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC);
+ efree(p);
+}
+
+#ifdef _WIN32
+extern "C"
+#endif
+static zend_object_value
+handleClone(zval* zv TSRMLS_DC)
+{
+ //
+ // Create a new object that shares a C++ proxy instance with this object.
+ //
+
+ zend_object_value result;
+ memset(&result, 0, sizeof(zend_object_value));
+
+ ProxyPtr obj = Wrapper<ProxyPtr>::value(zv TSRMLS_CC);
+ assert(obj);
+
+ zval* clone;
+ MAKE_STD_ZVAL(clone);
+ if(!obj->clone(clone, obj->proxy TSRMLS_CC))
+ {
+ return result;
+ }
+
+ //
+ // We only need to return the new object's handle, so we must destroy the zval containing
+ // a reference to the new object. We increment the object's reference count to ensure it
+ // does not get destroyed.
+ //
+ result = clone->value.obj;
+ Z_OBJ_HT_P(clone)->add_ref(clone TSRMLS_CC);
+ zval_dtor(clone);
+ efree(clone);
+
+ return result;
+}
+
+#ifdef _WIN32
+extern "C"
+#endif
+static union _zend_function*
+#if PHP_VERSION_ID < 50400
+handleGetMethod(zval** zv, char* method, int len TSRMLS_DC)
+#else
+handleGetMethod(zval** zv, char* method, int len, const _zend_literal* key TSRMLS_DC)
+#endif
+{
+ zend_function* result;
+
+ //
+ // First delegate to the standard implementation of get_method. This will find
+ // any of our predefined proxy methods. If it returns 0, then we return a
+ // function that will check the class definition.
+ //
+#if PHP_VERSION_ID < 50400
+ result = zend_get_std_object_handlers()->get_method(zv, method, len TSRMLS_CC);
+#else
+ result = zend_get_std_object_handlers()->get_method(zv, method, len, key TSRMLS_CC);
+#endif
+ if(!result)
+ {
+ Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(*zv TSRMLS_CC);
+ assert(obj->ptr);
+ ProxyPtr _this = *obj->ptr;
+
+ ClassInfoPtr info = _this->info;
+ assert(info);
+
+ OperationPtr op = info->getOperation(method);
+ if(!op)
+ {
+ //
+ // Returning 0 causes PHP to report an "undefined method" error.
+ //
+ return 0;
+ }
+
+ result = op->function();
+ }
+
+ return result;
+}
+
+#ifdef _WIN32
+extern "C"
+#endif
+static int
+handleCompare(zval* zobj1, zval* zobj2 TSRMLS_DC)
+{
+ //
+ // PHP guarantees that the objects have the same class.
+ //
+
+ Wrapper<ProxyPtr>* obj1 = Wrapper<ProxyPtr>::extract(zobj1 TSRMLS_CC);
+ assert(obj1->ptr);
+ ProxyPtr _this1 = *obj1->ptr;
+ Ice::ObjectPrx prx1 = _this1->proxy;
+
+ Wrapper<ProxyPtr>* obj2 = Wrapper<ProxyPtr>::extract(zobj2 TSRMLS_CC);
+ assert(obj2->ptr);
+ ProxyPtr _this2 = *obj2->ptr;
+ Ice::ObjectPrx prx2 = _this2->proxy;
+
+ if(prx1 == prx2)
+ {
+ return 0;
+ }
+ else if(prx1 < prx2)
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+//
+// Necessary to suppress warnings from zend_function_entry in php-5.2.
+//
+#if defined(__GNUC__)
+# pragma GCC diagnostic ignored "-Wwrite-strings"
+#endif
+
+//
+// Predefined methods for ObjectPrx.
+//
+static zend_function_entry _proxyMethods[] =
+{
+ ZEND_ME(Ice_ObjectPrx, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
+ ZEND_ME(Ice_ObjectPrx, __toString, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getCommunicator, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_toString, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getIdentity, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_identity, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getContext, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_context, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getFacet, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_facet, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getAdapterId, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_adapterId, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getEndpoints, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_endpoints, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getLocatorCacheTimeout, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getConnectionId, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_locatorCacheTimeout, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_isConnectionCached, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_connectionCached, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getEndpointSelection, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_endpointSelection, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_isSecure, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_secure, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getEncodingVersion, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_encodingVersion, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_isPreferSecure, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_preferSecure, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getRouter, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_router, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getLocator, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_locator, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_twoway, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_isTwoway, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_oneway, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_isOneway, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_batchOneway, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_isBatchOneway, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_datagram, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_isDatagram, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_batchDatagram, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_isBatchDatagram, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_compress, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_timeout, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_connectionId, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getConnection, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_getCachedConnection, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_flushBatchRequests, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_uncheckedCast, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ObjectPrx, ice_checkedCast, NULL, ZEND_ACC_PUBLIC)
+ {0, 0, 0}
+};
+
+//
+// enable warning again
+//
+#if defined(__GNUC__)
+# pragma GCC diagnostic error "-Wwrite-strings"
+#endif
+
+bool
+IcePHP::proxyInit(TSRMLS_D)
+{
+ //
+ // Register the ObjectPrx class.
+ //
+ zend_class_entry ce;
+#ifdef ICEPHP_USE_NAMESPACES
+ INIT_NS_CLASS_ENTRY(ce, "Ice", "ObjectPrx", _proxyMethods);
+#else
+ INIT_CLASS_ENTRY(ce, "Ice_ObjectPrx", _proxyMethods);
+#endif
+ ce.create_object = handleAlloc;
+ proxyClassEntry = zend_register_internal_class(&ce TSRMLS_CC);
+ //proxyClassEntry->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
+ memcpy(&_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ _handlers.clone_obj = handleClone;
+ _handlers.get_method = handleGetMethod;
+ _handlers.compare_objects = handleCompare;
+
+ return true;
+}
+
+bool
+IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const CommunicatorInfoPtr& comm TSRMLS_DC)
+{
+ return Proxy::create(zv, p, 0, comm TSRMLS_CC);
+}
+
+bool
+IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm
+ TSRMLS_DC)
+{
+ return Proxy::create(zv, p, info, comm TSRMLS_CC);
+}
+
+bool
+IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls TSRMLS_DC)
+{
+ CommunicatorInfoPtr comm;
+ return fetchProxy(zv, prx, cls, comm TSRMLS_CC);
+}
+
+bool
+IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls, CommunicatorInfoPtr& comm TSRMLS_DC)
+{
+ if(!ZVAL_IS_NULL(zv))
+ {
+ if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != proxyClassEntry)
+ {
+ invalidArgument("value is not a proxy" TSRMLS_CC);
+ return false;
+ }
+ Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(zv TSRMLS_CC);
+ if(!obj)
+ {
+ runtimeError("unable to retrieve proxy object from object store" TSRMLS_CC);
+ return false;
+ }
+ assert(obj->ptr);
+ prx = (*obj->ptr)->proxy;
+ cls = (*obj->ptr)->info;
+ comm = (*obj->ptr)->communicator;
+ }
+ return true;
+}