Move -DSWIG_DIRECTOR_STATIC handling there, so this is now supported for all languages with director support, not just Python and PHP.
170 lines
4.1 KiB
Text
170 lines
4.1 KiB
Text
/* -----------------------------------------------------------------------------
|
|
* director.swg
|
|
*
|
|
* This file contains support for director classes so that PHP proxy
|
|
* methods can be called from C++.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
#ifndef SWIG_DIRECTOR_PHP_HEADER_
|
|
#define SWIG_DIRECTOR_PHP_HEADER_
|
|
|
|
#include <string>
|
|
#include <exception>
|
|
#include <map>
|
|
|
|
namespace Swig {
|
|
|
|
/* memory handler */
|
|
struct GCItem {
|
|
virtual ~GCItem() {
|
|
}
|
|
|
|
virtual int get_own() const {
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
struct GCItem_var {
|
|
GCItem_var(GCItem *item = 0) : _item(item) {
|
|
}
|
|
|
|
GCItem_var& operator=(GCItem *item) {
|
|
GCItem *tmp = _item;
|
|
_item = item;
|
|
delete tmp;
|
|
return *this;
|
|
}
|
|
|
|
~GCItem_var() {
|
|
delete _item;
|
|
}
|
|
|
|
GCItem * operator->() const {
|
|
return _item;
|
|
}
|
|
|
|
private:
|
|
GCItem *_item;
|
|
};
|
|
|
|
struct GCItem_Object : GCItem {
|
|
GCItem_Object(int own) : _own(own) {
|
|
}
|
|
|
|
virtual ~GCItem_Object() {
|
|
}
|
|
|
|
int get_own() const {
|
|
return _own;
|
|
}
|
|
|
|
private:
|
|
int _own;
|
|
};
|
|
|
|
template <typename Type>
|
|
struct GCItem_T : GCItem {
|
|
GCItem_T(Type *ptr) : _ptr(ptr) {
|
|
}
|
|
|
|
virtual ~GCItem_T() {
|
|
delete _ptr;
|
|
}
|
|
|
|
private:
|
|
Type *_ptr;
|
|
};
|
|
|
|
class Director {
|
|
protected:
|
|
zval *swig_self;
|
|
typedef std::map<void *, GCItem_var> swig_ownership_map;
|
|
mutable swig_ownership_map swig_owner;
|
|
#ifdef ZTS
|
|
// Store the ZTS context so it's available when C++ calls back to PHP.
|
|
void *** swig_zts_ctx;
|
|
#endif
|
|
public:
|
|
Director(zval *self TSRMLS_DC) : swig_self(self) {
|
|
TSRMLS_SET_CTX(swig_zts_ctx);
|
|
}
|
|
|
|
static bool swig_is_overridden_method(char *cname, char *lc_fname TSRMLS_DC) {
|
|
zend_class_entry **ce;
|
|
zend_function *mptr;
|
|
|
|
if (zend_lookup_class(cname, strlen(cname), &ce TSRMLS_CC) != SUCCESS) {
|
|
return false;
|
|
}
|
|
if (zend_hash_find(&(*ce)->function_table, lc_fname, strlen(lc_fname) + 1, (void **) &mptr) != SUCCESS) {
|
|
return false;
|
|
}
|
|
// common.scope points to the declaring class
|
|
return strcmp(mptr->common.scope->name, cname);
|
|
}
|
|
|
|
template <typename Type>
|
|
void swig_acquire_ownership(Type *vptr) const {
|
|
if (vptr) {
|
|
swig_owner[vptr] = new GCItem_T<Type>(vptr);
|
|
}
|
|
}
|
|
};
|
|
|
|
/* base class for director exceptions */
|
|
class DirectorException : public std::exception {
|
|
protected:
|
|
std::string swig_msg;
|
|
public:
|
|
DirectorException(int code, const char *hdr, const char *msg TSRMLS_DC) : swig_msg(hdr) {
|
|
if (msg[0]) {
|
|
swig_msg += " ";
|
|
swig_msg += msg;
|
|
}
|
|
SWIG_ErrorCode() = code;
|
|
SWIG_ErrorMsg() = swig_msg.c_str();
|
|
}
|
|
|
|
virtual ~DirectorException() throw() {
|
|
}
|
|
|
|
const char *what() const throw() {
|
|
return swig_msg.c_str();
|
|
}
|
|
|
|
static void raise(int code, const char *hdr, const char *msg TSRMLS_DC) {
|
|
throw DirectorException(code, hdr, msg TSRMLS_CC);
|
|
}
|
|
};
|
|
|
|
/* attempt to call a pure virtual method via a director method */
|
|
class DirectorPureVirtualException : public DirectorException {
|
|
public:
|
|
DirectorPureVirtualException(const char *msg TSRMLS_DC)
|
|
: DirectorException(E_ERROR, "SWIG director pure virtual method called", msg TSRMLS_CC) {
|
|
}
|
|
|
|
static void raise(const char *msg TSRMLS_DC) {
|
|
throw DirectorPureVirtualException(msg TSRMLS_CC);
|
|
}
|
|
};
|
|
|
|
/* any php exception that occurs during a director method call */
|
|
class DirectorMethodException : public DirectorException
|
|
{
|
|
public:
|
|
DirectorMethodException(const char *msg TSRMLS_DC)
|
|
: DirectorException(E_ERROR, "SWIG director method error", msg TSRMLS_CC) {
|
|
}
|
|
|
|
static void raise(const char *msg TSRMLS_DC) {
|
|
throw DirectorMethodException(msg TSRMLS_CC);
|
|
}
|
|
};
|
|
}
|
|
|
|
// DirectorMethodException() is documented to be callable with no parameters
|
|
// so use a macro to insert TSRMLS_CC so any ZTS context gets passed.
|
|
#define DirectorMethodException() DirectorMethodException("" TSRMLS_CC)
|
|
|
|
#endif
|