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

@ -1,6 +1,24 @@
Version 1.3.18 (In progress)
============================
03/06/2003: mrose (Mark Rose)
Merged the cross-language polymorphism patch. When enabled, C++
"proxy" classes (called directors) for each specified C++ class.
Directors pass method calls from C++ to Python, similar to the way
the usual proxy (shadow) classes pass method calls from Python to
C++. Together, these two types of proxies allow C++ classes that
are extended in Python to behave just like ordinary C++ classes and
be used in C++ like native objects.
This feature is still very experimental and is disabled by default.
To enable director support, specify '-fdirectors' on the SWIG command
line or in the SWIG_FEATURES environment variable. In the interface
file, add %feature("director") to generate directors for all classes
that have virtual methods.
See http://stm.lbl.gov/~tm2/swig/ProxyDoc.html for more details.
03/03/2003: beazley
Fixed a small glitch in typemap local variable replacement. If you had
a typemap like this:

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)) {

View file

@ -140,6 +140,7 @@
#define WARN_TYPEMAP_VAR_UNDEF 466
#define WARN_TYPEMAP_TYPECHECK 467
#define WARN_TYPEMAP_THROW 468
#define WARN_TYPEMAP_INV_UNDEF 469
/* -- General code generation -- */
@ -156,6 +157,8 @@
#define WARN_LANG_OVERLOAD_KEYWORD 511
#define WARN_LANG_OVERLOAD_CONST 512
#define WARN_LANG_CLASS_UNNAMED 513
#define WARN_LANG_DIRECTOR_VDESTRUCT 514
#define WARN_LANG_DISCARD_CONST 515
/* -- Reserved (600-799) -- */

View file

@ -203,6 +203,7 @@ Language::Language() {
classtypes = NewHash();
overloading = 0;
multiinput = 0;
directors = 0;
}
Language::~Language() {
@ -1292,6 +1293,265 @@ int Language::typedefHandler(Node *) {
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* Language::classDirectorMethod()
* ---------------------------------------------------------------------- */
int Language::classDirectorMethod(Node *n, Node *parent, String* super) {
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* Language::classDirectorConstructor()
* ---------------------------------------------------------------------- */
int Language::classDirectorConstructor(Node *n) {
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* Language::classDirectorDefaultConstructor()
* ---------------------------------------------------------------------- */
int Language::classDirectorDefaultConstructor(Node *n) {
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* Language::tagDirectorBases()
* ---------------------------------------------------------------------- */
int Language::tagDirectorBases(Node *n) {
List* bl;
if (Getattr(n, "directorBase")) return SWIG_OK;
if (Getattr(n, "hasVirtual") == 0) return SWIG_OK;
Setattr(n, "directorBase", "1");
bl = Getattr(n, "bases");
if (bl) {
Node* bi;
for (bi = Firstitem(bl); bi; bi = Nextitem(bl)) {
tagDirectorBases(bi);
}
}
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* Language::unrollVirtualMethods()
* ---------------------------------------------------------------------- */
int Language::unrollVirtualMethods(Node *n,
Node *parent,
Hash *vm,
int default_director,
int &virtual_destructor,
int &has_virtual) {
int only_virtual = (Getattr(parent, "director:nonvirtual") == 0);
int top = (n == parent);
has_virtual = 0;
Node *ni;
String *type;
String *nodeType;
String *cdecl;
String *storage;
String *classname;
String *decl;
// default_director < 0 turns off director generation for this class and all its superclasses
if (default_director >= 0) {
if (Getattr(n, "feature:director")) default_director = 1;
if (Getattr(n, "feature:nodirector")) default_director = -1;
}
classname = Getattr(n, "name");
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
nodeType = Getattr(ni, "nodeType");
storage = Getattr(ni, "storage");
cdecl = Getattr(ni, "cdecl");
decl = Getattr(ni, "decl");
if (!Cmp(nodeType, "cdecl") && SwigType_isfunction(decl)) {
int is_virtual = storage && !Cmp(storage, "virtual");
if (is_virtual) has_virtual = 1;
String* access = Getattr(ni, "access");
if (!access || !Cmp(access, "public")) {
if (!only_virtual || is_virtual) {
String *method_id;
String *name = Getattr(ni, "name");
method_id = NewStringf("%s|%s", name, decl);
int director = default_director;
if (director >= 0) {
if (Getattr(ni, "feature:director")) director = 1;
if (Getattr(ni, "feature:nodirector")) director = 0;
}
if ((director == 1) && !Getattr(vm, method_id)) {
String *fqname = NewString("");
Printf(fqname, "%s::%s", classname, name);
Hash *item = NewHash();
Setattr(item, "fqName", fqname);
Setattr(item, "methodNode", ni);
Setattr(vm, method_id, item);
Delete(fqname);
Delete(item);
}
Delete(method_id);
}
}
}
else if (!Cmp(nodeType, "destructor")) {
if (storage && !Cmp(storage, "virtual")) {
virtual_destructor = 1;
}
}
else {
}
}
List* bl = Getattr(n, "bases");
if (bl) {
Node* bi;
for (bi = Firstitem(bl); bi; bi = Nextitem(bl)) {
int virtual_base = 0;
unrollVirtualMethods(bi, parent, vm, default_director, virtual_destructor, virtual_base);
if (virtual_base) {
has_virtual = 1;
}
}
}
if (has_virtual) {
Setattr(n, "hasVirtual", "1");
}
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* Language::classDirectorDisown()
* ---------------------------------------------------------------------- */
int Language::classDirectorDisown(Node *n) {
Node *disown = NewHash();
String *mrename;
String *symname = Getattr(n,"sym:name");
mrename = Swig_name_disown(symname); //Getattr(n, "name"));
String *type = NewString(ClassType);
String *name = NewString("self");
SwigType_add_pointer(type);
Parm *p = NewParm(type, name);
Delete(name);
Delete(type);
type = NewString("void");
String *action = NewString("");
Printv(action, "{\n",
"__DIRECTOR__ *director = dynamic_cast<__DIRECTOR__*>(arg1);\n",
"if (director) director->__disown();\n",
"}\n",
NULL);
Setattr(disown, "wrap:action", action);
Setattr(disown,"name", mrename);
Setattr(disown,"sym:name", mrename);
Setattr(disown,"type",type);
Setattr(disown,"parms", p);
Delete(action);
Delete(mrename);
Delete(type);
Delete(p);
functionWrapper(disown);
Delete(disown);
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* Language::classDirectorConstructors()
* ---------------------------------------------------------------------- */
int Language::classDirectorConstructors(Node *n) {
Node *ni;
String *nodeType;
int constructor = 0;
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
nodeType = Getattr(ni, "nodeType");
if (!Cmp(nodeType, "constructor")) {
classDirectorConstructor(ni);
constructor = 1;
}
}
if (!constructor) {
classDirectorDefaultConstructor(n);
}
}
/* ----------------------------------------------------------------------
* Language::classDirectorMethods()
* ---------------------------------------------------------------------- */
int Language::classDirectorMethods(Node *n) {
Node *vtable = Getattr(n, "vtable");
Node *item;
String *key;
for (key = Firstkey(vtable); key != 0; key = Nextkey(vtable)) {
item = Getattr(vtable, key);
String *method = Getattr(item, "methodNode");
String *fqname = Getattr(item, "fqName");
if (classDirectorMethod(method, n, fqname) == SWIG_OK) {
Setattr(item, "director", "1");
}
}
}
/* ----------------------------------------------------------------------
* Language::classDirectorInit()
* ---------------------------------------------------------------------- */
int Language::classDirectorInit(Node *n) {
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* Language::classDirectorEnd()
* ---------------------------------------------------------------------- */
int Language::classDirectorEnd(Node *n) {
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* Language::classDirector()
* ---------------------------------------------------------------------- */
int Language::classDirector(Node *n) {
Node *module = Getattr(n,"module");
String *classtype = Getattr(n, "classtype");
Hash *directormap = 0;
if (module) {
directormap = Getattr(module, "wrap:directormap");
if (directormap == 0) {
directormap = NewHash();
Setattr(module, "wrap:directormap", directormap);
}
}
Hash* vtable = NewHash();
int virtual_destructor = 0;
int has_virtual = 0;
unrollVirtualMethods(n, n, vtable, 0, virtual_destructor, has_virtual);
if (Len(vtable) > 0) {
if (!virtual_destructor) {
String *classtype = Getattr(n, "classtype");
Swig_warning(WARN_LANG_DIRECTOR_VDESTRUCT, input_file, line_number,
"Director base class %s has no virtual destructor.\n",
classtype);
}
Setattr(n, "vtable", vtable);
tagDirectorBases(n);
classDirectorInit(n);
classDirectorConstructors(n);
classDirectorMethods(n);
classDirectorEnd(n);
if (directormap != 0) {
Setattr(directormap, classtype, n);
}
}
Delete(vtable);
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* Language::classDeclaration()
* ---------------------------------------------------------------------- */
@ -1339,6 +1599,12 @@ int Language::classDeclaration(Node *n) {
}
Setattr(n,"classtype", SwigType_namestr(ClassType));
/*
if (CPlusPlus) {
classDirector(n);
}
*/
InClass = 1;
CurrentClass = n;
@ -1349,10 +1615,14 @@ int Language::classDeclaration(Node *n) {
}
/* Call classHandler() here */
if (!ImportMode)
if (!ImportMode) {
if (CPlusPlus && directorsEnabled()) {
classDirector(n);
}
classHandler(n);
else
} else {
Language::classHandler(n);
}
InClass = 0;
CurrentClass = 0;
@ -1399,6 +1669,12 @@ int Language::classHandler(Node *n) {
destructorHandler(CurrentClass);
}
}
/* emit director disown method */
if (Getattr(n, "vtable")) {
classDirectorDisown(n);
}
return SWIG_OK;
}
@ -1816,6 +2092,30 @@ void Language::allow_multiple_input(int val) {
multiinput = val;
}
/* -----------------------------------------------------------------------------
* Language::allow_directors()
* ----------------------------------------------------------------------------- */
void Language::allow_directors(int val) {
directors = val;
}
/* -----------------------------------------------------------------------------
* Language::directorsEnabled()
* ----------------------------------------------------------------------------- */
int Language::directorsEnabled() const {
return directors;
}
/* -----------------------------------------------------------------------------
* Language::is_smart_pointer()
* ----------------------------------------------------------------------------- */
int Language::is_smart_pointer() const {
return SmartPointer;
}
/* -----------------------------------------------------------------------------
* Language::is_wrapping_class()
* ----------------------------------------------------------------------------- */

View file

@ -72,6 +72,7 @@ static char *usage = (char*)"\
-swiglib - Report location of SWIG library and exit\n\
-v - Run in verbose mode\n\
-fcompact - Compile in compact mode\n\
-fdirectors - Enable C++ directors\n\
-fvirtual - Compile in virtual elimination mode\n\
-small - Compile in virtual elimination & compact mode\n\
-version - Print SWIG version number\n\
@ -189,6 +190,7 @@ int SWIG_main(int argc, char *argv[], Language *l) {
int dump_classes = 0;
int werror = 0;
int depend = 0;
int directors = 0;
DOH *libfiles = 0;
DOH *cpps = 0 ;
@ -285,6 +287,9 @@ int SWIG_main(int argc, char *argv[], Language *l) {
} else if (strcmp(temp, "-small") == 0) {
Wrapper_compact_print_mode_set(1);
Wrapper_virtual_elimination_mode_set(1);
} else if (strcmp(temp, "-fdirectors") == 0) {
directors = 1;
lang->allow_directors();
}
}
}
@ -324,6 +329,10 @@ int SWIG_main(int argc, char *argv[], Language *l) {
Wrapper_compact_print_mode_set(1);
Wrapper_virtual_elimination_mode_set(1);
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-fdirectors") == 0) {
directors = 1;
lang->allow_directors();
Swig_mark_arg(i);
} else if (strcmp(argv[i],"-c") == 0) {
NoInclude=1;
Preprocessor_define((DOH *) "SWIG_NOINCLUDE 1", 0);
@ -534,6 +543,9 @@ int SWIG_main(int argc, char *argv[], Language *l) {
if (lang_config) {
Printf(fs,"\n%%include \"%s\"\n", lang_config);
}
if (directors) {
Printf(fs,"\n%%include \"director.swg\"\n");
}
Printf(fs,"%%include \"%s\"\n", Swig_last_file());
for (i = 0; i < Len(libfiles); i++) {
Printf(fs,"\n%%include \"%s\"\n", Getitem(libfiles,i));
@ -631,8 +643,15 @@ int SWIG_main(int argc, char *argv[], Language *l) {
} else {
Setattr(top,"outfile", NewStringf("%s_wrap.c", Swig_file_basename(input_file)));
}
Setattr(top,"outfile_h", NewStringf("%s_wrap.h", Swig_file_basename(input_file)));
} else {
char *header = strdup(outfile_name);
char *ext = header + strlen(header);
while (ext > header && *ext != '.') ext--;
if (*ext == '.') *ext = 0;
Setattr(top,"outfile", outfile_name);
Setattr(top,"outfile_h", NewStringf("%s.h", header));
free(header);
}
if (contracts) {
Swig_contracts(top);

File diff suppressed because it is too large Load diff

View file

@ -178,23 +178,48 @@ public:
virtual int functionWrapper(Node *n);
virtual int nativeWrapper(Node *n);
/* C++ director class generation */
virtual int classDirector(Node *n);
virtual int classDirectorInit(Node *n);
virtual int classDirectorEnd(Node *n);
virtual int tagDirectorBases(Node *n);
virtual int unrollVirtualMethods(Node *n,
Node *parent,
Hash *vm,
int default_director,
int &virtual_destructor,
int &has_virtual);
virtual int classDirectorConstructor(Node *n);
virtual int classDirectorDefaultConstructor(Node *n);
virtual int classDirectorMethod(Node *n, Node *parent, String *super);
virtual int classDirectorConstructors(Node *n);
virtual int classDirectorMethods(Node *n);
virtual int classDirectorDisown(Node *n);
/* Miscellaneous */
virtual int validIdentifier(String *s); /* valid identifier? */
virtual int addSymbol(String *s, Node *n); /* Add symbol */
virtual Node *symbolLookup(String *s); /* Symbol lookup */
virtual Node *classLookup(SwigType *s); /* Class lookup */
/* Allow director related code generation */
void allow_directors(int val = 1);
/* Return true if directors are enabled */
int directorsEnabled() const;
protected:
/* Patch C++ pass-by-value */
static void patch_parms(Parm *p);
/* Allow overloaded functions */
void allow_overloading(int val = 1);
/* Allow multiple-input typemaps */
void allow_multiple_input(int val = 1);
/* Allow overloaded functions */
void allow_overloading(int val = 1);
/* Wrapping class query */
int is_wrapping_class();
@ -210,11 +235,16 @@ public:
/* Fully qualified type name to use */
String *getClassType() const;
/* Return true if the current method is part of a smart-pointer */
int is_smart_pointer() const;
private:
Hash *symbols;
Hash *classtypes;
int overloading;
int multiinput;
int directors;
};
extern int SWIG_main(int, char **, Language *);

View file

@ -341,13 +341,17 @@ Swig_cconstructor_call(String_or_char *name) {
* ----------------------------------------------------------------------------- */
String *
Swig_cppconstructor_call(String_or_char *name, ParmList *parms) {
Swig_cppconstructor_base_call(String_or_char *name, ParmList *parms, int skip_self, int disown) {
String *func;
String *nname;
int i = 0;
int comma = 0;
Parm *p = parms;
SwigType *pt;
if (skip_self) {
if (p) p = nextSibling(p);
i++;
}
nname = SwigType_namestr(name);
func = NewString("");
Printf(func,"new %s(", nname);
@ -363,11 +367,29 @@ Swig_cppconstructor_call(String_or_char *name, ParmList *parms) {
}
p = nextSibling(p);
}
if (disown >= 0) {
if (comma) Printf(func, ",");
Printf(func, "%d", disown);
}
Printf(func,")");
Delete(nname);
return func;
}
String *
Swig_cppconstructor_call(String_or_char *name, ParmList *parms) {
return Swig_cppconstructor_base_call(name, parms, 0, -1);
}
String *
Swig_cppconstructor_nodirector_call(String_or_char *name, ParmList *parms) {
return Swig_cppconstructor_base_call(name, parms, 1, -1);
}
String *
Swig_cppconstructor_director_call(String_or_char *name, ParmList *parms) {
return Swig_cppconstructor_base_call(name, parms, 0, 0);
}
/* -----------------------------------------------------------------------------
* Swig_cdestructor_call()
@ -473,7 +495,7 @@ Swig_MethodToFunction(Node *n, String *classname, int flags) {
name = Getattr(n,"name");
qualifier = Getattr(n,"qualifier");
parms = CopyParmList(nonvoid_parms(Getattr(n,"parms")));
type = NewString(classname);
if (qualifier) {
SwigType_push(type,qualifier);
@ -524,6 +546,62 @@ Swig_MethodToFunction(Node *n, String *classname, int flags) {
return SWIG_OK;
}
/* -----------------------------------------------------------------------------
* Swig_methodclass()
*
* This function returns the class node for a given method or class.
* ----------------------------------------------------------------------------- */
Node*
Swig_methodclass(Node *n) {
Node* type = Getattr(n, "nodeType");
if (!Cmp(type, "class")) return n;
return Getattr(n, "parentNode");
}
int
Swig_directorbase(Node *n) {
Node *classNode = Swig_methodclass(n);
return (classNode && (Getattr(classNode, "directorBase") != 0));
}
int
Swig_directorclass(Node *n) {
Node *classNode = Swig_methodclass(n);
return (Getattr(classNode, "vtable") != 0);
}
int
Swig_directormethod(Node *n) {
Node *classNode = Swig_methodclass(n);
if (classNode) {
Node *vtable = Getattr(classNode, "vtable");
if (vtable) {
String *name = Getattr(n, "name");
String *decl = Getattr(n, "decl");
String *method_id = NewStringf("%s|%s", name, decl);
Hash *item = Getattr(vtable, method_id);
Delete(method_id);
if (item) {
return (Getattr(item, "director") != 0);
}
}
}
return 0;
}
Node *
Swig_directormap(Node *module, String *type) {
int is_void = !Cmp(type, "void");
if (!is_void && module) {
String* base = SwigType_base(type);
Node *directormap = Getattr(module, "wrap:directormap");
if (directormap) return Getattr(directormap, base);
}
return 0;
}
/* -----------------------------------------------------------------------------
* Swig_ConstructorToFunction()
*
@ -537,10 +615,17 @@ Swig_ConstructorToFunction(Node *n, String *classname, int cplus, int flags)
SwigType *type;
String *membername;
String *mangled;
Node *classNode;
int use_director;
classNode = Swig_methodclass(n);
use_director = Swig_directorclass(n);
membername = Swig_name_construct(classname);
mangled = Swig_name_mangle(membername);
parms = CopyParmList(nonvoid_parms(Getattr(n,"parms")));
type = NewString(classname);
SwigType_add_pointer(type);
@ -558,7 +643,27 @@ Swig_ConstructorToFunction(Node *n, String *classname, int cplus, int flags)
Setattr(n,"wrap:action", Swig_cresult(type,"result", Swig_cfunction_call(mangled,parms)));
} else {
if (cplus) {
Setattr(n,"wrap:action", Swig_cresult(type,"result", Swig_cppconstructor_call(classname,parms)));
/* if a C++ director class exists, create it rather than the original class */
if (use_director) {
Node *parent = Swig_methodclass(n);
String *name = Getattr(parent, "sym:name");
String* directorname = NewStringf("__DIRECTOR__%s", name);
String* action = NewString("");
/* if Python class has been subclassed, create a director instance.
* otherwise, just create a normal instance.
*/
Printv(action, "if (arg1 != Py_None) { // subclassed\n",
Swig_cresult(type, "result", Swig_cppconstructor_director_call(directorname, parms)),
"} else {\n",
Swig_cresult(type, "result", Swig_cppconstructor_nodirector_call(classname, parms)),
"}\n",
NULL);
Setattr(n, "wrap:action", action);
Delete(action);
Delete(directorname);
} else {
Setattr(n,"wrap:action", Swig_cresult(type,"result", Swig_cppconstructor_call(classname,parms)));
}
} else {
Setattr(n,"wrap:action", Swig_cresult(type,"result", Swig_cconstructor_call(classname)));
}
@ -583,7 +688,8 @@ Swig_DestructorToFunction(Node *n, String *classname, int cplus, int flags)
{
SwigType *type;
Parm *p;
Node *classNode;
type = NewString(classname);
SwigType_add_pointer(type);
p = NewParm(type,"self");
@ -606,7 +712,9 @@ Swig_DestructorToFunction(Node *n, String *classname, int cplus, int flags)
Delete(mangled);
} else {
if (cplus) {
Setattr(n,"wrap:action", NewStringf("%s;\n", Swig_cppdestructor_call()));
String* action = NewString("");
Printf(action, "%s;\n", Swig_cppdestructor_call());
Setattr(n,"wrap:action", action);
} else {
Setattr(n,"wrap:action", NewStringf("%s;\n", Swig_cdestructor_call()));
}

View file

@ -341,6 +341,40 @@ String *Swig_name_destroy(const String_or_char *classname) {
return r;
}
/* -----------------------------------------------------------------------------
* Swig_name_disown()
*
* Returns the name of the accessor function used to disown an object.
* ----------------------------------------------------------------------------- */
String *Swig_name_disown(const String_or_char *classname) {
String *r;
String *f;
String *rclassname;
char *cname;
rclassname = SwigType_namestr(classname);
r = NewString("");
if (!naming_hash) naming_hash = NewHash();
f = Getattr(naming_hash,"disown");
if (!f) {
Append(r,"disown_%c");
} else {
Append(r,f);
}
cname = Char(rclassname);
if ((strncmp(cname,"struct ", 7) == 0) ||
((strncmp(cname,"class ", 6) == 0)) ||
((strncmp(cname,"union ", 6) == 0))) {
cname = strchr(cname, ' ')+1;
}
Replace(r,"%c",cname, DOH_REPLACE_ANY);
Delete(rclassname);
return r;
}
/* -----------------------------------------------------------------------------
* Swig_name_object_set()
*

View file

@ -347,6 +347,7 @@ SwigType_function_parms(SwigType *t) {
return firstp;
}
/* -----------------------------------------------------------------------------
* SwigType_add_template()
*
@ -561,6 +562,7 @@ String *SwigType_parm(SwigType *t) {
/* -----------------------------------------------------------------------------
* SwigType_ispointer()
* SwigType_ispointer_return()
* SwigType_isarray()
* SwigType_isreference()
* SwigType_isfunction()
@ -584,6 +586,30 @@ int SwigType_ispointer(SwigType *t) {
return 0;
}
int SwigType_ispointer_return(SwigType *t) {
char* c;
int idx;
if (!t) return 0;
c = Char(t);
idx = strlen(c)-4;
if (idx >= 0) {
return (strcmp(c+idx, ").p.") == 0);
}
return 0;
}
int SwigType_isreference_return(SwigType *t) {
char* c;
int idx;
if (!t) return 0;
c = Char(t);
idx = strlen(c)-4;
if (idx >= 0) {
return (strcmp(c+idx, ").r.") == 0);
}
return 0;
}
int SwigType_ismemberpointer(SwigType *t) {
char *c;
if (!t) return 0;

View file

@ -213,8 +213,10 @@ extern String *SwigType_lcaststr(SwigType *s, const String_or_char *id);
extern String *SwigType_manglestr(SwigType *t);
extern SwigType *SwigType_ltype(SwigType *t);
extern int SwigType_ispointer(SwigType *t);
extern int SwigType_ispointer_return(SwigType *t);
extern int SwigType_ismemberpointer(SwigType *t);
extern int SwigType_isreference(SwigType *t);
extern int SwigType_isreference_return(SwigType *t);
extern int SwigType_isarray(SwigType *t);
extern int SwigType_isfunction(SwigType *t);
extern int SwigType_isqualifier(SwigType *t);
@ -378,6 +380,7 @@ extern String *Swig_name_set(const String_or_char *vname);
extern String *Swig_name_construct(const String_or_char *classname);
extern String *Swig_name_copyconstructor(const String_or_char *classname);
extern String *Swig_name_destroy(const String_or_char *classname);
extern String *Swig_name_disown(const String_or_char *classname);
/* --- parameterized rename functions --- */
@ -443,6 +446,13 @@ extern int Swig_VarsetToFunction(Node *n);
#define CWRAP_EXTEND 0x01
#define CWRAP_SMART_POINTER 0x02
/* --- Director Helpers --- */
extern Node *Swig_methodclass(Node *n);
extern int Swig_directorbase(Node *n);
extern int Swig_directorclass(Node *n);
extern int Swig_directormethod(Node *n);
extern Node *Swig_directormap(Node *n, String *type);
/* --- Legacy Typemap API (somewhat simplified, ha!) --- */
extern void Swig_typemap_init();