Home | History | Annotate | Download | only in php
      1 /* -----------------------------------------------------------------------------
      2  * director.swg
      3  *
      4  * This file contains support for director classes that proxy
      5  * method calls from C++ to PHP extensions.
      6  * ----------------------------------------------------------------------------- */
      7 
      8 #ifndef SWIG_DIRECTOR_PHP_HEADER_
      9 #define SWIG_DIRECTOR_PHP_HEADER_
     10 
     11 #ifdef __cplusplus
     12 
     13 #include <string>
     14 #include <map>
     15 
     16 /*
     17   Use -DSWIG_DIRECTOR_STATIC if you prefer to avoid the use of the
     18   'Swig' namespace. This could be useful for multi-modules projects.
     19 */
     20 #ifdef SWIG_DIRECTOR_STATIC
     21 /* Force anonymous (static) namespace */
     22 #define Swig
     23 #endif
     24 
     25 namespace Swig {
     26   /* memory handler */
     27   struct GCItem
     28   {
     29     virtual ~GCItem() {}
     30 
     31     virtual int get_own() const
     32     {
     33       return 0;
     34     }
     35   };
     36 
     37   struct GCItem_var
     38   {
     39     GCItem_var(GCItem *item = 0) : _item(item)
     40     {
     41     }
     42 
     43     GCItem_var& operator=(GCItem *item)
     44     {
     45       GCItem *tmp = _item;
     46       _item = item;
     47       delete tmp;
     48       return *this;
     49     }
     50 
     51     ~GCItem_var()
     52     {
     53       delete _item;
     54     }
     55 
     56     GCItem * operator->() const
     57     {
     58       return _item;
     59     }
     60 
     61     private:
     62     GCItem *_item;
     63   };
     64 
     65   struct GCItem_Object : GCItem
     66   {
     67     GCItem_Object(int own) : _own(own)
     68     {
     69     }
     70 
     71     virtual ~GCItem_Object()
     72     {
     73     }
     74 
     75     int get_own() const
     76     {
     77       return _own;
     78     }
     79 
     80     private:
     81     int _own;
     82   };
     83 
     84   template <typename Type>
     85   struct GCItem_T : GCItem
     86   {
     87     GCItem_T(Type *ptr) : _ptr(ptr)
     88     {
     89     }
     90 
     91     virtual ~GCItem_T()
     92     {
     93       delete _ptr;
     94     }
     95 
     96     private:
     97     Type *_ptr;
     98   };
     99 
    100   class Director {
    101     protected:
    102       zval *swig_self;
    103       typedef std::map<void*, GCItem_var> swig_ownership_map;
    104       mutable swig_ownership_map swig_owner;
    105 #ifdef ZTS
    106       // Store the ZTS context so it's available when C++ calls back to PHP.
    107       void *** swig_zts_ctx;
    108 #endif
    109     public:
    110       Director(zval* self TSRMLS_DC) : swig_self(self) {
    111         TSRMLS_SET_CTX(swig_zts_ctx);
    112       }
    113 
    114       bool swig_is_overridden_method(char *cname, char *lc_fname) {
    115         TSRMLS_FETCH_FROM_CTX(swig_zts_ctx);
    116         zend_class_entry **ce;
    117         zend_function *mptr;
    118         int name_len = strlen(lc_fname);
    119 
    120         if (zend_lookup_class(cname, strlen(cname), &ce TSRMLS_CC) != SUCCESS) {
    121           return false;
    122         }
    123         if (zend_hash_find(&(*ce)->function_table, lc_fname, name_len + 1, (void**) &mptr) != SUCCESS) {
    124           return false;
    125         }
    126         // common.scope points to the declaring class
    127         return strcmp(mptr->common.scope->name, cname);
    128       }
    129 
    130       template <typename Type>
    131       void swig_acquire_ownership(Type *vptr) const
    132       {
    133         if (vptr) {
    134           swig_owner[vptr] = new GCItem_T<Type>(vptr);
    135         }
    136       }
    137   };
    138 
    139   /* base class for director exceptions */
    140   class DirectorException {
    141   protected:
    142     std::string swig_msg;
    143   public:
    144     DirectorException(int code, const char *hdr, const char* msg TSRMLS_DC)
    145       : swig_msg(hdr)
    146     {
    147       if (strlen(msg)) {
    148         swig_msg += " ";
    149         swig_msg += msg;
    150       }
    151       SWIG_ErrorCode() = code;
    152       SWIG_ErrorMsg() = swig_msg.c_str();
    153     }
    154 
    155     static void raise(int code, const char *hdr, const char* msg TSRMLS_DC)
    156     {
    157       throw DirectorException(code, hdr, msg TSRMLS_CC);
    158     }
    159   };
    160 
    161   /* attempt to call a pure virtual method via a director method */
    162   class DirectorPureVirtualException : public Swig::DirectorException
    163   {
    164   public:
    165     DirectorPureVirtualException(const char* msg TSRMLS_DC)
    166       : DirectorException(E_ERROR, "SWIG director pure virtual method called", msg TSRMLS_CC)
    167     {
    168     }
    169 
    170     static void raise(const char *msg TSRMLS_DC)
    171     {
    172       throw DirectorPureVirtualException(msg TSRMLS_CC);
    173     }
    174   };
    175   /* any php exception that occurs during a director method call */
    176   class DirectorMethodException : public Swig::DirectorException
    177   {
    178   public:
    179     DirectorMethodException(const char* msg TSRMLS_DC)
    180       : DirectorException(E_ERROR, "SWIG director method error", msg TSRMLS_CC)
    181     {
    182     }
    183 
    184     static void raise(const char *msg TSRMLS_DC)
    185     {
    186       throw DirectorMethodException(msg TSRMLS_CC);
    187     }
    188   };
    189 }
    190 
    191 // DirectorMethodException() is documented to be callable with no parameters
    192 // so use a macro to insert TSRMLS_CC so any ZTS context gets passed.
    193 #define DirectorMethodException() DirectorMethodException("" TSRMLS_CC)
    194 
    195 #endif /* __cplusplus */
    196 
    197 #endif
    198