polymorphism patch merge

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@4435 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Mark Rose 2003-03-06 19:21:58 +00:00
commit bd40a83f1c
15 changed files with 2007 additions and 15 deletions

View file

@ -0,0 +1,183 @@
/***********************************************************************
* director.swg
*
* This file contains support for director classes that proxy
* method calls from C++ to Python extensions.
*
* Author : Mark Rose (mrose@stm.lbl.gov)
************************************************************************/
%insert(runtime) %{
#ifdef __cplusplus
#include <string>
/* base class for director exceptions */
class SWIG_DIRECTOR_EXCEPTION {
protected:
std::string _msg;
public:
SWIG_DIRECTOR_EXCEPTION(const char* msg="") {
}
const char *getMessage() { return _msg.c_str(); }
virtual ~SWIG_DIRECTOR_EXCEPTION() { }
};
/* type mismatch in the return value from a python method call */
class SWIG_DIRECTOR_TYPE_MISMATCH: public SWIG_DIRECTOR_EXCEPTION {
public:
SWIG_DIRECTOR_TYPE_MISMATCH(const char* msg="") {
_msg = "Swig director type mismatch: ";
_msg += msg;
PyErr_SetString(PyExc_TypeError, msg);
}
};
/* any python exception that occurs during a director method call */
class SWIG_DIRECTOR_METHOD_EXCEPTION: public SWIG_DIRECTOR_EXCEPTION { };
/* simple thread abstraction for pthreads or win32 */
#ifdef __THREAD__
#define __PTHREAD__
#if defined(_WIN32) || defined(__WIN32__)
#define pthread_mutex_lock EnterCriticalSection
#define pthread_mutex_unlock LeaveCriticalSection
#define pthread_mutex_t CRITICAL_SECTION
#define MUTEX_INIT(var) CRITICAL_SECTION var
#else
#include <pthread.h>
#define MUTEX_INIT(var) pthread_mutex_t var = PTHREAD_MUTEX_INITIALIZER
#endif
#endif
/* director base class */
class __DIRECTOR__ {
private:
/* pointer to the wrapped python object */
PyObject* _self;
/* flag indicating whether the object is owned by python or c++ */
mutable int _disown;
/* shared flag for breaking recursive director calls */
static int _up;
#ifdef __PTHREAD__
/* locks for sharing the _up flag in a threaded environment */
static pthread_mutex_t _mutex_up;
static int _mutex_active;
static pthread_t _mutex_thread;
#endif
/* decrement the reference count of the wrapped python object */
void __decref() const {
assert(_self);
if (_disown) {
Py_DECREF(_self);
}
}
/* reset the _up flag once the routing direction has been determined */
#ifdef __PTHREAD__
void __clear_up() const {
__DIRECTOR__::_up = 0;
__DIRECTOR__::_mutex_active = 0;
pthread_mutex_unlock(&_mutex_up);
}
#else
void __clear_up() const {
__DIRECTOR__::_up = 0;
}
#endif
public:
/* the default constructor should not be called */
__DIRECTOR__() {
assert(0);
}
/* wrap a python object, optionally taking ownership */
__DIRECTOR__(PyObject* self, int disown): _self(self), _disown(disown) {
__incref();
}
/* discard our reference at destruction */
virtual ~__DIRECTOR__() {
__decref();
}
/* return a pointer to the wrapped python object */
PyObject *__get_self() const {
return _self;
}
/* get the _up flag to determine if the method call should be routed
* to the c++ base class or through the wrapped python object
*/
#ifdef __PTHREAD__
int __get_up() const {
if (__DIRECTOR__::_mutex_active) {
if (pthread_equal(__DIRECTOR__::_mutex_thread, pthread_self())) {
int up = _up;
__clear_up();
return up;
}
}
return 0;
}
#else
int __get_up() const {
int up = _up;
_up = 0;
return up;
}
#endif
/* set the _up flag if the next method call should be directed to
* the c++ base class rather than the wrapped python object
*/
#ifdef __PTHREAD__
void __set_up() const {
pthread_mutex_lock(&__DIRECTOR__::_mutex_up);
__DIRECTOR__::_mutex_thread = pthread_self();
__DIRECTOR__::_mutex_active = 1;
__DIRECTOR__::_up = 1;
}
#else
void __set_up() const {
__DIRECTOR__::_up = 1;
}
#endif
/* acquire ownership of the wrapped python object (the sense of "disown"
* is from python) */
void __disown() const {
assert(_self);
if (!_disown) {
_disown=1;
__incref();
}
}
/* increase the reference count of the wrapped python object */
void __incref() const {
assert(_self);
if (_disown) {
Py_INCREF(_self);
}
}
};
int __DIRECTOR__::_up = 0;
#ifdef __PTHREAD__
MUTEX_INIT(__DIRECTOR__::_mutex_up);
pthread_t __DIRECTOR__::_mutex_thread;
int __DIRECTOR__::_mutex_active = 0;
#endif
#endif /* __cplusplus */
%}

View file

@ -22,6 +22,126 @@
* standard typemaps
* ----------------------------------------------------------------------------- */
/*****************************************************************************
*
* Inverse argument typemaps are for marshaling C/C++ parameters to call Python
* methods from C++ proxy wrapper classes.
*
*****************************************************************************/
/* --- Inverse arguments --- */
/* Primitive datatypes. These only supply a parse code to PyObject_CallMethod */
%typemap(inv,parse="i") int "";
%typemap(inv,parse="h") short "";
%typemap(inv,parse="l") long "";
%typemap(inv,parse="b") signed char "";
%typemap(inv,parse="f") float "";
%typemap(inv,parse="d") double "";
%typemap(inv,parse="s") char* "";
%typemap(inv,parse="i") bool "";
%typemap(inv,parse="l") unsigned int, unsigned short, unsigned long, unsigned char "(long) $1_name";
%typemap(inv) long long
"$input = PyLong_FromLongLong($1_name);";
%typemap(inv) unsigned long long
"$input = PyLong_FromUnsignedLongLong($1_name);";
%typemap(inv, parse="l") int *INV, long* INV,
unsigned int *INV, unsigned long *INV,
short *INV, unsigned short *INV,
char *INV, unsigned char *INV
"(long) *$1_name";
%typemap(inv, parse="f") float *INV "*$1_name";
%typemap(inv, parse="d") double *INV "*$1_name";
%typemap(inv, parse="O") PyObject* "";
/*
%typemap(inv, parse="s") SWIGTYPE {
{
$&1_ltype resultptr;
resultptr = new $1_ltype(($1_ltype &) $1);
$result = SWIG_NewPointerObj((void *) resultptr, $&1_descriptor, 1);
}
}
*/
/* no can do... see python.cxx
%typemap(inv) DIRECTORTYPE * {
{
__DIRECTOR__$1_ltype proxy = dynamic_cast<__DIRECTOR__$1_ltype>($1_name);
if (!proxy) {
$input = SWIG_NewPointerObj((void *) $1_name, $1_descriptor, 0);
} else {
$input = proxy->__get_self();
}
assert($input);
}
}
%typemap(inv) SWIGTYPE * {
$input = SWIG_NewPointerObj((void *) $1_name, $1_descriptor, 0);
}
*/
/*
%typemap(inv, parse="s") void "0";
*/
/*
%typemap(inv) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] {
$input = SWIG_NewPointerObj((void *) $1_name, $1_descriptor, $owner);
}
*/
/* --- Outverse arguments --- */
%define OUTV_TYPEMAP(type, converter)
%typemap(argoutv) type *OUTV
"*$result = (type) converter($input);
if (PyErr_Occurred()) throw SWIG_DIRECTOR_TYPE_MISMATCH(\"Error converting Python object using converter\");";
%typemap(outv) type
"$result = (type) converter($input);
if (PyErr_Occurred()) throw SWIG_DIRECTOR_TYPE_MISMATCH(\"Error converting Python object using converter\");";
%typemap(outv) type &OUTV = type
%enddef
OUTV_TYPEMAP(char, PyInt_AsLong);
OUTV_TYPEMAP(unsigned char, PyInt_AsLong);
OUTV_TYPEMAP(short, PyInt_AsLong);
OUTV_TYPEMAP(unsigned short, PyInt_AsLong);
OUTV_TYPEMAP(int, PyInt_AsLong);
OUTV_TYPEMAP(unsigned int, PyInt_AsLong);
OUTV_TYPEMAP(long, PyInt_AsLong);
OUTV_TYPEMAP(unsigned long, PyInt_AsLong);
OUTV_TYPEMAP(long long, PyLong_AsLongLong);
OUTV_TYPEMAP(unsigned long long, PyLong_AsUnsignedLongLong);
OUTV_TYPEMAP(float, PyFloat_AsDouble);
OUTV_TYPEMAP(double, PyFloat_AsDouble);
OUTV_TYPEMAP(bool, PyInt_AsLong);
OUTV_TYPEMAP(PyObject *, );
OUTV_TYPEMAP(char *, PyString_AsString);
%typemap(outv) SWIGTYPE *,
SWIGTYPE &,
SWIGTYPE []
"if ((SWIG_ConvertPtr($input,(void **) &$result, $descriptor,SWIG_POINTER_EXCEPTION | $disown )) == -1) throw SWIG_DIRECTOR_TYPE_MISMATCH(\"Pointer conversion failed.\");";
%typemap(outv) void * "if ((SWIG_ConvertPtr($input,(void **) &$result, 0, SWIG_POINTER_EXCEPTION | $disown )) == -1) throw SWIG_DIRECTOR_TYPE_MISMATCH(\"Pointer conversion failed.\");";
/*****************************************************************************
*
* End of C++ proxy wrapper typemaps.
*
*****************************************************************************/
/* --- Input arguments --- */
/* Primitive datatypes. These only supply a parse code to PyTuple_ParseArgs */
@ -495,6 +615,11 @@
}
}
%typecheck(SWIG_TYPECHECK_POINTER) PyObject *
{
$1 = ($input != 0);
}
/* ------------------------------------------------------------
* Exception handling
* ------------------------------------------------------------ */

View file

@ -64,6 +64,47 @@ SwigComplex_AsComplexDouble(PyObject *o)
%typemap(out) const Complex & {
$result = PyComplex_FromDoubles($1->real(), $1->imag());
}
// C++ proxy class typemaps
%typemap(inv) complex<T> {
$input = PyComplex_FromDoubles($1_name.real(), $1_name.imag());
}
%typemap(inv) const complex<T> & {
$inupt = PyComplex_FromDoubles($1_name->real(), $1_name->imag());
}
%typemap(outv) complex<T> {
if (PyComplex_Check($input)) {
$result = std::complex<T>(PyComplex_RealAsDouble($input),
PyComplex_ImagAsDouble($input));
} else if (PyFloat_Check($input)) {
$result = std::complex<T>(PyFloat_AsDouble($input), 0);
} else if (PyInt_Check($input)) {
$result = std::complex<T>(PyInt_AsLong($input), 0);
}
else {
throw SWIG_DIRECTOR_TYPE_MISMATCH("Expected a complex");
}
}
%typemap(outv) const complex<T>& (std::complex<T> temp) {
if (PyComplex_Check($input)) {
temp = std::complex<T>(PyComplex_RealAsDouble($input),
PyComplex_ImagAsDouble($input));
$result = &temp;
} else if (PyFloat_Check($input)) {
temp = std::complex<T>(PyFloat_AsDouble($input), 0);
$result = &temp;
} else if (PyInt_Check($input)) {
temp = std::complex<T>(PyInt_AsLong($input), 0);
$result = &temp;
} else {
throw SWIG_DIRECTOR_TYPE_MISMATCH("Expected a complex");
}
}
%enddef

View file

@ -50,5 +50,26 @@ namespace std {
%typemap(out) const string & {
$result = PyString_FromStringAndSize($1->data(),$1->size());
}
%typemap(inv, parse="s") string, const string &, string & "$1_name.c_str()";
%typemap(inv, parse="s") string *, const string * "$1_name->c_str()";
%typemap(outv) string {
if (PyString_Check($input))
$result = std::string(PyString_AsString($input));
else
throw SWIG_DIRECTOR_TYPE_MISMATCH("string expected");
}
%typemap(outv) const string & (std::string temp) {
if (PyString_Check($input)) {
temp = std::string(PyString_AsString($input));
$result = &temp;
} else {
throw SWIG_DIRECTOR_TYPE_MISMATCH("string expected");
}
}
}

View file

@ -106,6 +106,31 @@ namespace std {
SWIG_fail;
}
}
%typemap(outv) vector<T> (std::vector<T>* v) {
if (PyTuple_Check($input) || PyList_Check($input)) {
unsigned int size = (PyTuple_Check($input) ?
PyTuple_Size($input) :
PyList_Size($input));
$result = std::vector<T >(size);
for (unsigned int i=0; i<size; i++) {
T* x;
PyObject* o = PySequence_GetItem($input,i);
if ((SWIG_ConvertPtr(o,(void **) &x,
$descriptor(T *),0)) != -1) {
(($type &)$result)[i] = *x;
Py_DECREF(o);
} else {
Py_DECREF(o);
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
} else if (SWIG_ConvertPtr($input,(void **) &v,
$&descriptor,1) != -1){
$result = *v;
} else {
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
%typemap(in) const vector<T>& (std::vector<T> temp,
std::vector<T>* v),
const vector<T>* (std::vector<T> temp,
@ -138,6 +163,35 @@ namespace std {
SWIG_fail;
}
}
%typemap(outv) const vector<T>& (std::vector<T> temp,
std::vector<T>* v),
const vector<T>* (std::vector<T> temp,
std::vector<T>* v) {
if (PyTuple_Check($input) || PyList_Check($input)) {
unsigned int size = (PyTuple_Check($input) ?
PyTuple_Size($input) :
PyList_Size($input));
temp = std::vector<T >(size);
$result = &temp;
for (unsigned int i=0; i<size; i++) {
T* x;
PyObject* o = PySequence_GetItem($input,i);
if ((SWIG_ConvertPtr(o,(void **) &x,
$descriptor(T *),0)) != -1) {
temp[i] = *x;
Py_DECREF(o);
} else {
Py_DECREF(o);
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
} else if (SWIG_ConvertPtr($input,(void **) &v,
$descriptor,1) != -1){
$result = v;
} else {
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
%typemap(out) vector<T> {
$result = PyTuple_New($1.size());
for (unsigned int i=0; i<$1.size(); i++) {
@ -147,6 +201,15 @@ namespace std {
$descriptor(T *), 1));
}
}
%typemap(inv) vector<T> {
$input = PyTuple_New($1.size());
for (unsigned int i=0; i<$1.size(); i++) {
T* ptr = new T((($1_type &)$1)[i]);
PyTuple_SetItem($input,i,
SWIG_NewPointerObj((void *) ptr,
$descriptor(T *), 1));
}
}
%typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
/* native sequence? */
if (PyTuple_Check($input) || PyList_Check($input)) {
@ -323,6 +386,31 @@ namespace std {
SWIG_fail;
}
}
%typemap(outv) vector<T> (std::vector<T>* v) {
if (PyTuple_Check($input) || PyList_Check($input)) {
unsigned int size = (PyTuple_Check($input) ?
PyTuple_Size($input) :
PyList_Size($input));
$result = std::vector<T >(size);
for (unsigned int i=0; i<size; i++) {
T x;
PyObject* o = PySequence_GetItem($input,i);
if ((SWIG_ConvertPtr(o,(void **) &x,
$descriptor(T),0)) != -1) {
(($type &)$result)[i] = x;
Py_DECREF(o);
} else {
Py_DECREF(o);
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
} else if (SWIG_ConvertPtr($input,(void **) &v,
$&descriptor,1) != -1){
$result = *v;
} else {
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
%typemap(in) const vector<T>& (std::vector<T> temp,
std::vector<T>* v),
const vector<T>* (std::vector<T> temp,
@ -355,6 +443,35 @@ namespace std {
SWIG_fail;
}
}
%typemap(outv) const vector<T>& (std::vector<T> temp,
std::vector<T>* v),
const vector<T>* (std::vector<T> temp,
std::vector<T>* v) {
if (PyTuple_Check($input) || PyList_Check($input)) {
unsigned int size = (PyTuple_Check($input) ?
PyTuple_Size($input) :
PyList_Size($input));
temp = std::vector<T >(size);
$result = &temp;
for (unsigned int i=0; i<size; i++) {
T x;
PyObject* o = PySequence_GetItem($input,i);
if ((SWIG_ConvertPtr(o,(void **) &x,
$descriptor(T),0)) != -1) {
temp[i] = x;
Py_DECREF(o);
} else {
Py_DECREF(o);
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
} else if (SWIG_ConvertPtr($input,(void **) &v,
$descriptor,1) != -1){
$result = v;
} else {
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
%typemap(out) vector<T> {
$result = PyTuple_New($1.size());
for (unsigned int i=0; i<$1.size(); i++) {
@ -364,6 +481,15 @@ namespace std {
$descriptor(T), 0));
}
}
%typemap(inv) vector<T> {
$input = PyTuple_New($1_name.size());
for (unsigned int i=0; i<$1_name.size(); i++) {
T ptr = (($1_type &)$1)[i];
PyTuple_SetItem($input,i,
SWIG_NewPointerObj((void *) ptr,
$descriptor(T), 0));
}
}
%typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
/* native sequence? */
if (PyTuple_Check($input) || PyList_Check($input)) {
@ -537,6 +663,29 @@ namespace std {
SWIG_fail;
}
}
%typemap(outv) vector<T> (std::vector<T>* v) {
if (PyTuple_Check($input) || PyList_Check($input)) {
unsigned int size = (PyTuple_Check($input) ?
PyTuple_Size($input) :
PyList_Size($input));
$result = std::vector<T >(size);
for (unsigned int i=0; i<size; i++) {
PyObject* o = PySequence_GetItem($input,i);
if (CHECK(o)) {
(($type &)$result)[i] = (T)(CONVERT_FROM(o));
Py_DECREF(o);
} else {
Py_DECREF(o);
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
} else if (SWIG_ConvertPtr($input,(void **) &v,
$&descriptor,1) != -1){
$result = *v;
} else {
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
%typemap(in) const vector<T>& (std::vector<T> temp,
std::vector<T>* v),
const vector<T>* (std::vector<T> temp,
@ -567,12 +716,45 @@ namespace std {
SWIG_fail;
}
}
%typemap(outv) const vector<T>& (std::vector<T> temp,
std::vector<T>* v),
const vector<T>* (std::vector<T> temp,
std::vector<T>* v) {
if (PyTuple_Check($input) || PyList_Check($input)) {
unsigned int size = (PyTuple_Check($input) ?
PyTuple_Size($input) :
PyList_Size($input));
temp = std::vector<T >(size);
$result = &temp;
for (unsigned int i=0; i<size; i++) {
PyObject* o = PySequence_GetItem($input,i);
if (CHECK(o)) {
temp[i] = (T)(CONVERT_FROM(o));
Py_DECREF(o);
} else {
Py_DECREF(o);
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
} else if (SWIG_ConvertPtr($input,(void **) &v,
$descriptor,1) != -1){
$result = v;
} else {
throw SWIG_DIRECTOR_TYPE_MISMATCH("vector<" #T "> expected");
}
}
%typemap(out) vector<T> {
$result = PyTuple_New($1.size());
for (unsigned int i=0; i<$1.size(); i++)
PyTuple_SetItem($result,i,
CONVERT_TO((($1_type &)$1)[i]));
}
%typemap(inv) vector<T> {
$input = PyTuple_New($1_name.size());
for (unsigned int i=0; i<$1_name.size(); i++)
PyTuple_SetItem($input,i,
CONVERT_TO((($1_type &)$1_name)[i]));
}
%typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
/* native sequence? */
if (PyTuple_Check($input) || PyList_Check($input)) {