Abstract directors and typemap fixes.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@5024 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Mark Rose 2003-08-30 05:03:34 +00:00
commit c1b57370b6
10 changed files with 97 additions and 17 deletions

View file

@ -1,5 +1,19 @@
Version 1.3.20 (In progress)
============================
08/29/2003: mrose (Mark Rose)
Completed initial support for wrapping abstract classes with directors.
Constructor wrappers will be generated for abstract classes that have
directors, and instances of the director classes will be created regardless
of whether the proxy class has been subclassed in the target language.
No checks are made during construction to ensure that all pure virtual
methods are implemented in the target language. Instead, calls to
unimplemented methods will throw SWIG_DIRECTOR_PURE_VIRTUAL exceptions in
C++.
Integrated Prabhu Ramachandran's typemap patches, which provide director
typemap support for enums and std::size_t, and fix a couple bugs in the
director std::vector<> typemaps.
08/29/2003: cheetah (William Fulton)
[C#] Implemented exception handling for throwing C# exceptions from C/C++ code.
A few delegate functions are available for calling which then throw the C#

View file

@ -101,6 +101,7 @@ CPP_TEST_CASES += \
default_constructor \
default_ns \
default_ref \
director_abstract \
director_basic \
director_exception \
director_finalizer \

View file

@ -0,0 +1,26 @@
%module(directors="1") director_abstract
%{
#include <string>
class Foo {
public:
virtual ~Foo() {}
virtual std::string ping() = 0;
virtual std::string pong() { return "Foo::pong();" + ping(); }
};
%}
%include "typemaps.i"
%include "exception.i"
%include "std_string.i"
%feature("director") Foo;
class Foo {
public:
virtual ~Foo() {}
virtual std::string ping() = 0;
virtual std::string pong() { return "Foo::pong();" + ping(); }
};

View file

@ -0,0 +1,16 @@
import director_abstract
class MyFoo(director_abstract.Foo):
def ping(self):
return "MyFoo::ping()"
a = MyFoo()
if a.ping() != "MyFoo::ping()":
raise RuntimeError, a.ping()
if a.pong() != "Foo::pong();MyFoo::ping()":
raise RuntimeError, a.pong()

View file

@ -53,6 +53,7 @@ class SWIG_DIRECTOR_PURE_VIRTUAL_EXCEPTION: public SWIG_DIRECTOR_EXCEPTION { };
#endif
#endif
/* director base class */
class __DIRECTOR__ {
private:
@ -171,6 +172,7 @@ public:
};
namespace {
int __DIRECTOR__::_up = 0;
#ifdef __PTHREAD__
@ -179,6 +181,8 @@ int __DIRECTOR__::_up = 0;
int __DIRECTOR__::_mutex_active = 0;
#endif
}
#endif /* __cplusplus */

View file

@ -435,6 +435,7 @@
%typemap(inv,parse="d") double "";
%typemap(inv,parse="s") char* "";
%typemap(inv,parse="i") bool "";
%typemap(inv,parse="i") enum SWIGTYPE "";
%typemap(inv,parse="l") unsigned int, unsigned short, unsigned long, unsigned char "(long) $1_name";
@ -453,6 +454,7 @@
%typemap(inv, parse="O") PyObject* "";
%typemap(inv, parse="l") std::size_t "(long) $input";
/* // this is rather dangerous
%typemap(inv) SWIGTYPE {
@ -514,6 +516,7 @@ OUTV_TYPEMAP(double, PyFloat_AsDouble);
OUTV_TYPEMAP(bool, PyInt_AsLong);
OUTV_TYPEMAP(PyObject *, );
OUTV_TYPEMAP(char *, PyString_AsString);
OUTV_TYPEMAP(std::size_t, PyInt_AsLong);
/* Object returned by value. Convert from a pointer */
%typemap(outv) SWIGTYPE ($&ltype argp)

View file

@ -72,7 +72,7 @@ SwigComplex_AsComplexDouble(PyObject *o)
}
%typemap(inv) const complex<T> & {
$inupt = PyComplex_FromDoubles($1_name->real(), $1_name->imag());
$input = PyComplex_FromDoubles($1_name->real(), $1_name->imag());
}
%typemap(outv) complex<T> {

View file

@ -203,9 +203,9 @@ namespace std {
}
}
%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]);
$input = PyTuple_New($1_name.size());
for (unsigned int i=0; i<$1_name.size(); i++) {
T* ptr = new T((($1_type &)$1_name)[i]);
PyTuple_SetItem($input,i,
SWIG_NewPointerObj((void *) ptr,
$descriptor(T *), 1));
@ -486,7 +486,7 @@ namespace std {
%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];
T ptr = (($1_type &)$1_name)[i];
PyTuple_SetItem($input,i,
SWIG_NewPointerObj((void *) ptr,
$descriptor(T), 0));

View file

@ -1640,6 +1640,8 @@ int Language::classDeclaration(Node *n) {
int Language::classHandler(Node *n) {
bool hasDirector = Swig_directorclass(n);
/* Emit all of the class members */
emit_children(n);
@ -1659,7 +1661,7 @@ int Language::classHandler(Node *n) {
if (!ImportMode && (GenerateDefault && !Getattr(n,"feature:nodefault"))) {
if (!Getattr(n,"has_constructor") && !Getattr(n,"allocate:has_constructor") && (Getattr(n,"allocate:default_constructor"))) {
/* Note: will need to change this to support different kinds of classes */
if (!Abstract) {
if (!Abstract || hasDirector) {
Setattr(CurrentClass,"feature:new","1");
constructorHandler(CurrentClass);
Delattr(CurrentClass,"feature:new");
@ -1671,7 +1673,7 @@ int Language::classHandler(Node *n) {
}
/* emit director disown method */
if (Getattr(n, "vtable")) {
if (hasDirector) {
classDirectorDisown(n);
}

View file

@ -650,24 +650,38 @@ Swig_ConstructorToFunction(Node *n, String *classname,
if (cplus) {
/* if a C++ director class exists, create it rather than the original class */
if (use_director) {
int abstract = Getattr(n, "abstract") != 0;
Node *parent = Swig_methodclass(n);
String *name = Getattr(parent, "sym:name");
String* directorname = NewStringf("__DIRECTOR__%s", name);
String* action = NewString("");
String* tmp_none_comparison = Copy(none_comparison);
String* director_call;
String* nodirector_call;
Replaceall( tmp_none_comparison, "$arg", "arg1" );
/* if Python class has been subclassed, create a director instance.
* otherwise, just create a normal instance.
*/
/* arty: arg1 != Py_None => tmp_none_comparison */
Printv(action, "if (",tmp_none_comparison,") {/* 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);
director_call = Swig_cppconstructor_director_call(directorname, parms);
nodirector_call = Swig_cppconstructor_nodirector_call(classname, parms);
if (abstract) {
/* whether or not the abstract class has been subclassed in python,
* create a director instance (there's no way to create a normal
* instance). if any of the pure virtual methods haven't been
* implemented in the target language, calls to those methods will
* generate SWIG_DIRECTOR_PURE_VIRTUAL exceptions.
*/
Printv(action, Swig_cresult(type, "result", director_call), NULL);
} else {
/* if the proxy class has been subclassed, create a director instance.
* otherwise, just create a normal instance.
*/
Printv(action,
"if (",tmp_none_comparison,") {/* subclassed */\n",
Swig_cresult(type, "result", director_call),
"} else {\n",
Swig_cresult(type, "result", nodirector_call),
"}\n", NULL);
}
Setattr(n, "wrap:action", action);
Delete(tmp_none_comparison);
Delete(action);