fix director + abstract + constructors, reported by Brian Kelley

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@6478 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2004-10-22 07:25:42 +00:00
commit 114c703acd
9 changed files with 258 additions and 38 deletions

View file

@ -1,4 +1,4 @@
%module(directors="1") director_abstract
%module(directors="1",dirprot="1") director_abstract
%{
#include <string>
@ -17,36 +17,122 @@ public:
class Foo {
public:
virtual ~Foo() {}
virtual std::string ping() = 0;
virtual std::string pong() { return "Foo::pong();" + ping(); }
virtual ~Foo() {}
virtual std::string ping() = 0;
virtual std::string pong() { return "Foo::pong();" + ping(); }
};
%feature("director") Example1;
%feature("director");
%inline %{
class Example1
class Example0
{
private:
protected:
int xsize, ysize;
int fontsize;
int fontdim[23];
int xsize, ysize;
public:
Example0(int x, int y)
: xsize(x), ysize(y) { }
Example0() { }
public:
Example1()
: xsize(200), ysize(200) { }
virtual ~Example0() {}
int GetXSize() const { return xsize; }
// pure virtual methods that must be overridden
virtual int Color(unsigned char r, unsigned char g, unsigned char b)
{
return 0;
}
virtual ~Example1() {}
int GetXSize() const { return xsize; }
// pure virtual methods that must be overridden
virtual int Color(unsigned char r, unsigned char g, unsigned char b) = 0;
static int get_color(Example0 *ptr, unsigned char r,
unsigned char g, unsigned char b) {
return ptr->Color(r, g, b);
}
};
class Example1
{
protected:
int xsize, ysize;
public:
Example1(int x, int y)
: xsize(x), ysize(y) { }
Example1() { }
public:
virtual ~Example1() {}
int GetXSize() const { return xsize; }
// pure virtual methods that must be overridden
virtual int Color(unsigned char r, unsigned char g, unsigned char b) = 0;
static int get_color(Example1 *ptr, unsigned char r,
unsigned char g, unsigned char b) {
return ptr->Color(r, g, b);
}
};
class Example2
{
protected:
int xsize, ysize;
protected:
Example2(int x, int y)
: xsize(x), ysize(y) { }
public:
virtual ~Example2() {}
int GetXSize() const { return xsize; }
// pure virtual methods that must be overridden
virtual int Color(unsigned char r, unsigned char g, unsigned char b) = 0;
static int get_color(Example2 *ptr, unsigned char r,
unsigned char g, unsigned char b) {
return ptr->Color(r, g, b);
}
};
namespace ns
{
template <class T>
class Example3
{
public:
Example3()
{
}
Example3(int x, int y) { }
virtual ~Example3() {}
// pure virtual methods that must be overridden
virtual int Color(unsigned char r, unsigned char g, unsigned char b) = 0;
static int get_color(Example3 *ptr, unsigned char r,
unsigned char g, unsigned char b) {
return ptr->Color(r, g, b);
}
};
}
%}
%template(Example3_i) ns::Example3<int>;

View file

@ -16,15 +16,47 @@ if a.pong() != "Foo::pong();MyFoo::ping()":
raise RuntimeError, a.pong()
class MyExample(director_abstract.Example1):
def __init__(self):
director_abstract.Example1.__init__(self)
pass
class MyExample1(director_abstract.Example1):
def Color(self, r, g, b):
return r
me = MyExample()
class MyExample2(director_abstract.Example2):
def Color(self, r, g, b):
return g
print me.Color(1,2,3)
class MyExample3(director_abstract.Example3_i):
def Color(self, r, g, b):
return b
me1 = MyExample1()
if MyExample1.get_color(me1, 1,2,3) != 1:
raise RuntimeError
me2 = MyExample2(1,2)
if MyExample2.get_color(me2, 1,2,3) != 2:
raise RuntimeError
me3 = MyExample3()
if MyExample3.get_color(me3, 1,2,3) != 3:
raise RuntimeError
error = 1
try:
me1 = director_abstract.Example1()
except:
error = 0
if (error): raise RuntimeError
error = 1
try:
me2 = director_abstract.Example2()
except:
error = 0
if (error): raise RuntimeError
error = 1
try:
me3 = director_abstract.Example3_i()
except:
error = 0
if (error): raise RuntimeError

View file

@ -18,3 +18,14 @@ if a.pong != "Foo::pong();MyFoo::ping()"
end
class MyExample1 < Director_abstract::Example1
def color(r,g,b)
r
end
end
#m1 = MyExample1.new
#
#if m1.color(1,2,3) != 1
# raise RuntimeError, m1.color
#end

View file

@ -164,6 +164,7 @@
#define WARN_LANG_DIRECTOR_VDESTRUCT 514
#define WARN_LANG_DISCARD_CONST 515
#define WARN_LANG_OVERLOAD_IGNORED 516
#define WARN_LANG_DIRECTOR_ABSTRACT 517
/* -- Reserved (600-799) -- */

View file

@ -248,10 +248,12 @@ int Dispatcher::accessDeclaration(Node *n) { return defaultHandler(n); }
int Dispatcher::usingDeclaration(Node *n) { return defaultHandler(n); }
int Dispatcher::namespaceDeclaration(Node *n) { return defaultHandler(n); }
/* Allocators */
Language::Language() :
none_comparison(NewString("$arg != 0")),
director_ctor_code(NewString("")),
director_prot_ctor_code(0),
symbols(NewHash()),
classtypes(NewHash()),
enumtypes(NewHash()),
@ -270,6 +272,11 @@ Language::Language() :
" $nondirector_new \n",
"}\n", NIL);
/*
Default director 'protected' constructor code, disable by
default. Each language that need it, has to define it.
*/
director_prot_ctor_code = 0;
}
Language::~Language() {
@ -1665,7 +1672,7 @@ int Language::classDirectorConstructors(Node *n) {
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
nodeType = Getattr(ni, "nodeType");
if (!Cmp(nodeType, "constructor")) {
if (is_public(ni)) {
if (is_public(ni) || (dirprot_mode() && is_protected(ni))) {
classDirectorConstructor(ni);
constructor = 1;
}
@ -1960,6 +1967,7 @@ int Language::classHandler(Node *n) {
Iterator k;
int old_mode = cplus_mode;
cplus_mode = CPLUS_PROTECTED;
for (k = First(vtable); k.key; k = Next(k)) {
item = k.item;
Node *method = Getattr(item, "methodNode");
@ -2002,9 +2010,22 @@ int Language::constructorDeclaration(Node *n) {
String *symname = Getattr(n,"sym:name");
if (!CurrentClass) return SWIG_NOWRAP;
if (cplus_mode != CPLUS_PUBLIC) return SWIG_NOWRAP;
if (ImportMode) return SWIG_NOWRAP;
int need_prot = 0;
if ((cplus_mode != CPLUS_PUBLIC) && directorsEnabled()) {
need_prot = director_prot_ctor_code && dirprot_mode()
&& Swig_directorclass(CurrentClass) && is_protected(n);
if (need_prot) {
Node *parent = Swig_methodclass(n);
name = Getattr(parent,"name");
symname = Getattr(parent,"sym:name");
Setattr(n,"name",name);
Setattr(n,"sym:name",symname);
}
}
if ((cplus_mode != CPLUS_PUBLIC) && !need_prot) return SWIG_NOWRAP;
/* Name adjustment for %name */
Swig_save("constructorDeclaration",n,"sym:name",NIL);
@ -2067,7 +2088,18 @@ Language::constructorHandler(Node *n) {
Swig_require("constructorHandler",n,"?name","*sym:name","?type","?parms",NIL);
String *symname = Getattr(n,"sym:name");
String *mrename = Swig_name_construct(symname);
Swig_ConstructorToFunction(n, ClassType, none_comparison, director_ctor_code, CPlusPlus, Getattr(n, "template") ? 0 :Extend);
String *director_ctor = director_ctor_code;
if (!is_public(n)) {
if (director_prot_ctor_code && is_protected(n)) {
director_ctor = director_prot_ctor_code;
}
}
if (Getattr(Swig_methodclass(n),"abstract")) {
if (director_prot_ctor_code) {
director_ctor = director_prot_ctor_code;
}
}
Swig_ConstructorToFunction(n, ClassType, none_comparison, director_ctor, CPlusPlus, Getattr(n, "template") ? 0 :Extend);
Setattr(n,"sym:name", mrename);
functionWrapper(n);
Delete(mrename);
@ -2554,9 +2586,30 @@ String * Language::getClassType() const {
* ----------------------------------------------------------------------------- */
int Language::abstractClassTest(Node *n) {
return (Getattr(n,"abstract") ? 1 : 0);
List *abstract = Getattr(n,"abstract");
if (!abstract) return 0;
if (abstract && Cmp(Getattr(n, "feature:director"), "1")) return 1;
/*
since now %feature("noabstract") is working, we check
that the director is really not abstract.
*/
int dirabstract = 0;
for (int i = 0; i < Len(abstract); i++) {
Node *nn = Getitem(abstract,i);
if (!is_member_director(n,nn)) {
dirabstract = 1;
}
}
if (dirabstract) {
Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT,Getfile(n),Getline(n),
"Director class '%s' is abstract\n",
SwigType_namestr(Getattr(n,"name")));
}
return dirabstract;
}
void Language::setSubclassInstanceCheck(String *nc) {
none_comparison = nc;
}

View file

@ -68,6 +68,18 @@ static File *f_int_to_enum = 0;
class OCAML : public Language {
public:
OCAML()
{
director_prot_ctor_code = NewString("");
Printv(director_prot_ctor_code,
"if ( $comparison ) { /* subclassed */\n",
" $director_new \n",
"} else {\n",
" failwith(\"accessing abstract class or protected constructor\"); \n",
"}\n", NIL);
}
String *Swig_class_name(Node *n) {
String *name;
name = Copy(Getattr(n, "sym:name"));

View file

@ -82,7 +82,20 @@ Python Options (available with -python)\n\
class PYTHON : public Language {
public:
PYTHON()
{
/* Add code to manage protected constructors and directors */
director_prot_ctor_code = NewString("");
Printv(director_prot_ctor_code,
"if ( $comparison ) { /* subclassed */\n",
" $director_new \n",
"} else {\n",
" PyErr_SetString(PyExc_RuntimeError,",
" \"accessing abstract class or protected constructor\"); \n",
" SWIG_fail;\n",
"}\n", NIL);
}
/* ------------------------------------------------------------
* main()
* ------------------------------------------------------------ */

View file

@ -187,6 +187,15 @@ public:
f_init = 0;
useGlobalModule = false;
multipleInheritance = false;
director_prot_ctor_code = NewString("");
Printv(director_prot_ctor_code,
"if ( $comparison ) { /* subclassed */\n",
" $director_new \n",
"} else {\n",
" rb_raise(rb_eRuntimeError,\"accessing abstract class or protected constructor\"); \n",
" result = 0;\n",
"}\n", NIL);
}
/* ---------------------------------------------------------------------
@ -622,15 +631,15 @@ public:
String *s = NewString("");
String *temp = NewString("");
#ifdef SWIG_PROTECTED_TARGET_METHODS
const char* rb_define_method = is_public(n) ?
"rb_define_method" : "rb_define_protected_method" ;
#else
const char* rb_define_method = "rb_define_method";
#endif
switch (current) {
case MEMBER_FUNC:
{
#ifdef SWIG_PROTECTED_TARGET_METHODS
const char* rb_define_method = is_public(n) ?
"rb_define_method" : "rb_define_protected_method" ;
#else
const char* rb_define_method = "rb_define_method";
#endif
if (multipleInheritance) {
Printv(klass->init, tab4, rb_define_method,"(", klass->mImpl, ", \"",
iname, "\", ", wname, ", -1);\n", NIL);
@ -645,7 +654,7 @@ public:
Replaceall(klass->init,"$allocator", s);
break;
case CONSTRUCTOR_INITIALIZE:
Printv(s, tab4, "rb_define_method(", klass->vname,
Printv(s, tab4, rb_define_method,"(", klass->vname,
", \"initialize\", ", wname, ", -1);\n", NIL);
Replaceall(klass->init,"$initializer", s);
break;

View file

@ -269,6 +269,9 @@ public:
/* Director constructor "template" code */
String *director_ctor_code;
/* Director 'protected' constructor "template" code*/
String *director_prot_ctor_code;
private:
Hash *symbols;
Hash *classtypes;