merge from trunk

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2009-sploving@11489 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Baozeng Ding 2009-08-02 01:20:12 +00:00
commit 21671f7534
86 changed files with 3689 additions and 502 deletions

198
Lib/php/director.swg Normal file
View file

@ -0,0 +1,198 @@
/* -----------------------------------------------------------------------------
* See the LICENSE file for information on copyright, usage and redistribution
* of SWIG, and the README file for authors - http://www.swig.org/release.html.
*
* director.swg
*
* This file contains support for director classes that proxy
* method calls from C++ to PHP extensions.
* ----------------------------------------------------------------------------- */
#ifndef SWIG_DIRECTOR_PHP_HEADER_
#define SWIG_DIRECTOR_PHP_HEADER_
#ifdef __cplusplus
#include <string>
#include <map>
/*
Use -DSWIG_DIRECTOR_STATIC if you prefer to avoid the use of the
'Swig' namespace. This could be useful for multi-modules projects.
*/
#ifdef SWIG_DIRECTOR_STATIC
/* Force anonymous (static) namespace */
#define Swig
#endif
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> ownership_map;
mutable ownership_map owner;
public:
Director(zval* self) : swig_self(self) {
}
~Director() {
for (ownership_map::iterator i = owner.begin(); i != owner.end(); i++) {
owner.erase(i);
}
}
bool is_overriden_method(char *cname, char *lc_fname) {
zval classname;
zend_class_entry **ce;
zend_function *mptr;
int name_len = strlen(lc_fname);
ZVAL_STRING(&classname, cname, 0);
if (zend_lookup_class(Z_STRVAL_P(&classname), Z_STRLEN_P(&classname), &ce TSRMLS_CC) != SUCCESS) {
return false;
}
if (zend_hash_find(&(*ce)->function_table, lc_fname, name_len + 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) {
owner[vptr] = new GCItem_T<Type>(vptr);
}
}
};
/* base class for director exceptions */
class DirectorException {
protected:
std::string swig_msg;
public:
DirectorException(int code, const char *hdr, const char* msg)
: swig_msg(hdr)
{
if (strlen(msg)) {
swig_msg += " ";
swig_msg += msg;
}
SWIG_ErrorCode() = code;
SWIG_ErrorMsg() = swig_msg.c_str();
}
static void raise(int code, const char *hdr, const char* msg)
{
throw DirectorException(code, hdr, msg);
}
};
/* attempt to call a pure virtual method via a director method */
class DirectorPureVirtualException : public Swig::DirectorException
{
public:
DirectorPureVirtualException(const char* msg)
: DirectorException(E_ERROR, "Swig director pure virtual method called", msg)
{
}
static void raise(const char *msg)
{
throw DirectorPureVirtualException(msg);
}
};
/* any php exception that occurs during a director method call */
class DirectorMethodException : public Swig::DirectorException
{
public:
DirectorMethodException(const char* msg = "")
: DirectorException(E_ERROR, "Swig director method error", msg)
{
}
static void raise(const char *msg)
{
throw DirectorMethodException(msg);
}
};
}
#endif /* __cplusplus */
#endif

109
Lib/php/factory.i Normal file
View file

@ -0,0 +1,109 @@
/*
Implement a more natural wrap for factory methods, for example, if
you have:
---- geometry.h --------
struct Geometry {
enum GeomType{
POINT,
CIRCLE
};
virtual ~Geometry() {}
virtual int draw() = 0;
//
// Factory method for all the Geometry objects
//
static Geometry *create(GeomType i);
};
struct Point : Geometry {
int draw() { return 1; }
double width() { return 1.0; }
};
struct Circle : Geometry {
int draw() { return 2; }
double radius() { return 1.5; }
};
//
// Factory method for all the Geometry objects
//
Geometry *Geometry::create(GeomType type) {
switch (type) {
case POINT: return new Point();
case CIRCLE: return new Circle();
default: return 0;
}
}
---- geometry.h --------
You can use the %factory with the Geometry::create method as follows:
%newobject Geometry::create;
%factory(Geometry *Geometry::create, Point, Circle);
%include "geometry.h"
and Geometry::create will return a 'Point' or 'Circle' instance
instead of the plain 'Geometry' type. For example, in python:
circle = Geometry.create(Geometry.CIRCLE)
r = circle.radius()
where circle is a Circle proxy instance.
NOTES: remember to fully qualify all the type names and don't
use %factory inside a namespace declaration, ie, instead of
namespace Foo {
%factory(Geometry *Geometry::create, Point, Circle);
}
use
%factory(Foo::Geometry *Foo::Geometry::create, Foo::Point, Foo::Circle);
*/
/* for loop for macro with one argument */
%define %_formacro_1(macro, arg1,...)macro(arg1)
#if #__VA_ARGS__ != "__fordone__"
%_formacro_1(macro, __VA_ARGS__)
#endif
%enddef
/* for loop for macro with one argument */
%define %formacro_1(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef
%define %formacro(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef
/* for loop for macro with two arguments */
%define %_formacro_2(macro, arg1, arg2, ...)macro(arg1, arg2)
#if #__VA_ARGS__ != "__fordone__"
%_formacro_2(macro, __VA_ARGS__)
#endif
%enddef
/* for loop for macro with two arguments */
%define %formacro_2(macro,...)%_formacro_2(macro, __VA_ARGS__, __fordone__)%enddef
%define %_factory_dispatch(Type)
if (!dcast) {
Type *dobj = dynamic_cast<Type *>($1);
if (dobj) {
dcast = 1;
SWIG_SetPointerZval(return_value, SWIG_as_voidptr(dobj),$descriptor(Type *), $owner);
}
}%enddef
%define %factory(Method,Types...)
%typemap(out) Method {
int dcast = 0;
%formacro(%_factory_dispatch, Types)
if (!dcast) {
SWIG_SetPointerZval(return_value, SWIG_as_voidptr($1),$descriptor, $owner);
}
}%enddef

View file

@ -89,6 +89,14 @@
$1 = *tmp;
}
%typemap(directorout) SWIGTYPE ($&1_ltype tmp)
{
if(SWIG_ConvertPtr(*$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) {
SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor");
}
$result = *tmp;
}
%typemap(in) SWIGTYPE *,
SWIGTYPE []
{
@ -176,17 +184,42 @@
ZVAL_LONG(return_value,$1);
}
%typemap(directorin) int,
unsigned int,
short,
unsigned short,
long,
unsigned long,
signed char,
unsigned char,
size_t,
enum SWIGTYPE
{
ZVAL_LONG($input,$1_name);
}
%typemap(out) bool
{
ZVAL_BOOL(return_value,($1)?1:0);
}
%typemap(directorin) bool
{
ZVAL_BOOL($input,($1_name)?1:0);
}
%typemap(out) float,
double
{
ZVAL_DOUBLE(return_value,$1);
}
%typemap(directorin) float,
double
{
ZVAL_DOUBLE($input,$1_name);
}
%typemap(out) char
{
ZVAL_STRINGL(return_value,&$1, 1, 1);
@ -209,6 +242,13 @@
SWIG_SetPointerZval(return_value, (void *)$1, $1_descriptor, $owner);
%}
%typemap(directorin) SWIGTYPE *,
SWIGTYPE [],
SWIGTYPE &
%{
SWIG_SetPointerZval($input, (void *)&$1_name, $1_descriptor, $owner);
%}
%typemap(out) SWIGTYPE *DYNAMIC,
SWIGTYPE &DYNAMIC
{
@ -230,6 +270,19 @@
}
#endif
%typemap(directorin) SWIGTYPE
#ifdef __cplusplus
{
SWIG_SetPointerZval($input, SWIG_as_voidptr(&$1_name), $&1_descriptor, 2);
}
#else
{
$&1_ltype resultobj = ($&1_ltype) emalloc(sizeof($1_type));
memcpy(resultobj, &$1, sizeof($1_type));
SWIG_SetPointerZval($input, (void *)resultobj, $&1_descriptor, 2);
}
#endif
%typemap(out) void "";
%typemap(out) char [ANY]

View file

@ -3,19 +3,13 @@
* of SWIG, and the README file for authors - http://www.swig.org/release.html.
*
* phpkw.swg
*
* The 'keywords' in PHP are global, ie, the following names are fine
* when used as class methods.
* ----------------------------------------------------------------------------- */
#define PHPKW(x) %keywordwarn("'" `x` "' is a PHP keyword, renamed as 'c_" `x` "'",sourcefmt="%(lower)s", rename="c_%s",fullname=1) `x`
#define PHPKW(x) %keywordwarn("'" `x` "' is a PHP keyword, renamed as 'c_" `x` "'",sourcefmt="%(lower)s",$isclass,rename="c_%s") `x`
%define PHPCN(x)
%keywordwarn("'" `x` "' is a PHP reserved class name, class renamed as 'c_" `x` "'",%$isclass,rename="c_%s") `x`;
%keywordwarn("'" `x` "' is a PHP reserved class name, constructor renamed as 'c_" `x` "'",%$isconstructor,rename="c_%s") `x`;
%enddef
#define PHPCN(x) %keywordwarn("'" `x` "' is a PHP reserved class name, class renamed as 'c_" `x` "'",%$isclass,rename="c_%s") `x`
#define PHPBN1(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP",sourcefmt="%(lower)s",fullname=1) `x`
#define PHPBN1(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP",sourcefmt="%(lower)s") `x`
#define PHPBN2(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP") "::" `x`

View file

@ -13,6 +13,7 @@ extern "C" {
#include "zend.h"
#include "zend_API.h"
#include "php.h"
#include "ext/standard/php_string.h"
#ifdef ZEND_RAW_FENTRY
/* ZEND_RAW_FENTRY was added somewhere between 5.2.0 and 5.2.3 */
@ -84,6 +85,7 @@ typedef struct {
static ZEND_RSRC_DTOR_FUNC(SWIG_landfill) { (void)rsrc; }
#define SWIG_SetPointerZval(a,b,c,d) SWIG_ZTS_SetPointerZval(a,b,c,d TSRMLS_CC)
#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a))
static void
SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject TSRMLS_DC) {
@ -101,7 +103,31 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject
value=(swig_object_wrapper *)emalloc(sizeof(swig_object_wrapper));
value->ptr=ptr;
value->newobject=newobject;
ZEND_REGISTER_RESOURCE(z, value, *(int *)(type->clientdata));
if (newobject <= 1) {
ZEND_REGISTER_RESOURCE(z, value, *(int *)(type->clientdata));
} else {
value->newobject = 0;
zval *resource;
MAKE_STD_ZVAL(resource);
ZEND_REGISTER_RESOURCE(resource, value, *(int *)(type->clientdata));
zend_class_entry **ce = NULL;
zval *classname;
MAKE_STD_ZVAL(classname);
/* _p_Foo -> Foo */
ZVAL_STRING(classname, (char*)type->name+3, 1);
/* class names are stored in lowercase */
php_strtolower(Z_STRVAL_PP(&classname), Z_STRLEN_PP(&classname));
if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &ce TSRMLS_CC) != SUCCESS) {
/* class does not exists */
object_init(z);
} else {
object_init_ex(z, *ce);
}
z->refcount = 1;
z->is_ref = 1;
zend_hash_update(HASH_OF(z), (char*)"_cPtr", sizeof("_cPtr"), (void*)&resource, sizeof(zval), NULL);
FREE_ZVAL(classname);
}
return;
}
zend_error(E_ERROR, "Type: %s not registered with zend",type->name);
@ -156,7 +182,7 @@ SWIG_ZTS_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags TSRMLS_DC) {
char *type_name;
value = (swig_object_wrapper *) zend_list_find(z->value.lval, &type);
if ( flags && SWIG_POINTER_DISOWN ) {
if ( flags & SWIG_POINTER_DISOWN ) {
value->newobject = 0;
}
p = value->ptr;

View file

@ -35,6 +35,11 @@ namespace std {
$1.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input));
%}
%typemap(directorout) string %{
convert_to_string_ex($input);
$result.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input));
%}
%typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) const string& %{
$1 = ( Z_TYPE_PP($input) == IS_STRING ) ? 1 : 0;
%}
@ -43,6 +48,10 @@ namespace std {
ZVAL_STRINGL($result, const_cast<char*>($1.data()), $1.size(), 1);
%}
%typemap(directorin) string %{
ZVAL_STRINGL($input, const_cast<char*>($1_name.data()), $1_name.size(), 1);
%}
%typemap(out) const string & %{
ZVAL_STRINGL($result, const_cast<char*>($1->data()), $1->size(), 1);
%}
@ -63,6 +72,14 @@ namespace std {
$1 = &temp;
%}
%typemap(directorout) string & (std::string *temp) %{
convert_to_string_ex($input);
temp = new std::string;
temp->assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input));
swig_acquire_ownership(temp);
$result = temp;
%}
%typemap(argout) string & %{
ZVAL_STRINGL(*($input), const_cast<char*>($1->data()), $1->size(), 1);
%}

View file

@ -37,6 +37,10 @@
%{
CONVERT_IN($1,$1_ltype,$input);
%}
%typemap(directorout) TYPE, const TYPE &
%{
CONVERT_IN($result,$1_ltype,$input);
%}
%enddef
%fragment("t_output_helper","header") %{
@ -49,6 +53,7 @@ t_output_helper( zval **target, zval *o) {
}
if ( (*target)->type == IS_NULL ) {
REPLACE_ZVAL_VALUE(target,o,1);
FREE_ZVAL(o);
return;
}
zval *tmp;

View file

@ -20,6 +20,7 @@
typedef std::map<K,T> map_type;
static int asptr(PyObject *obj, map_type **val) {
int res = SWIG_ERROR;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
if (PyDict_Check(obj)) {
SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL);
%#if PY_VERSION_HEX >= 0x03000000
@ -32,6 +33,7 @@
res = SWIG_ConvertPtr(obj,(void**)&p,swig::type_info<map_type>(),0);
if (SWIG_IsOK(res) && val) *val = p;
}
SWIG_PYTHON_THREAD_END_BLOCK;
return res;
}
};
@ -47,10 +49,10 @@
if (desc && desc->clientdata) {
return SWIG_NewPointerObj(new map_type(map), desc, SWIG_POINTER_OWN);
} else {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
size_type size = map.size();
int pysize = (size <= (size_type) INT_MAX) ? (int) size : -1;
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
@ -62,6 +64,7 @@
swig::SwigVar_PyObject val = swig::from(i->second);
PyDict_SetItem(obj, key, val);
}
SWIG_PYTHON_THREAD_END_BLOCK;
return obj;
}
}
@ -165,8 +168,8 @@
PyObject* keys() {
Map::size_type size = self->size();
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
@ -177,14 +180,15 @@
for (int j = 0; j < pysize; ++i, ++j) {
PyList_SET_ITEM(keyList, j, swig::from(i->first));
}
SWIG_PYTHON_THREAD_END_BLOCK;
return keyList;
}
PyObject* values() {
Map::size_type size = self->size();
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
@ -195,14 +199,15 @@
for (int j = 0; j < pysize; ++i, ++j) {
PyList_SET_ITEM(valList, j, swig::from(i->second));
}
SWIG_PYTHON_THREAD_END_BLOCK;
return valList;
}
PyObject* items() {
Map::size_type size = self->size();
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
@ -213,6 +218,7 @@
for (int j = 0; j < pysize; ++i, ++j) {
PyList_SET_ITEM(itemList, j, swig::from(*i));
}
SWIG_PYTHON_THREAD_END_BLOCK;
return itemList;
}