fix director + abstract + constructors, reported by Brian Kelley
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@6478 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
f7ae968d6b
commit
df9fa977a8
9 changed files with 258 additions and 38 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
%module(directors="1") director_abstract
|
%module(directors="1",dirprot="1") director_abstract
|
||||||
%{
|
%{
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -17,36 +17,122 @@ public:
|
||||||
|
|
||||||
class Foo {
|
class Foo {
|
||||||
public:
|
public:
|
||||||
virtual ~Foo() {}
|
virtual ~Foo() {}
|
||||||
virtual std::string ping() = 0;
|
virtual std::string ping() = 0;
|
||||||
virtual std::string pong() { return "Foo::pong();" + ping(); }
|
virtual std::string pong() { return "Foo::pong();" + ping(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%feature("director") Example1;
|
%feature("director");
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
class Example1
|
class Example0
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int xsize, ysize;
|
int xsize, ysize;
|
||||||
int fontsize;
|
|
||||||
int fontdim[23];
|
public:
|
||||||
|
|
||||||
|
Example0(int x, int y)
|
||||||
|
: xsize(x), ysize(y) { }
|
||||||
|
|
||||||
|
Example0() { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Example1()
|
virtual ~Example0() {}
|
||||||
: xsize(200), ysize(200) { }
|
|
||||||
|
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() {}
|
static int get_color(Example0 *ptr, unsigned char r,
|
||||||
|
unsigned char g, unsigned char b) {
|
||||||
int GetXSize() const { return xsize; }
|
return ptr->Color(r, g, b);
|
||||||
|
}
|
||||||
// pure virtual methods that must be overridden
|
|
||||||
virtual int Color(unsigned char r, unsigned char g, unsigned char b) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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>;
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,47 @@ if a.pong() != "Foo::pong();MyFoo::ping()":
|
||||||
raise RuntimeError, a.pong()
|
raise RuntimeError, a.pong()
|
||||||
|
|
||||||
|
|
||||||
class MyExample(director_abstract.Example1):
|
class MyExample1(director_abstract.Example1):
|
||||||
def __init__(self):
|
|
||||||
director_abstract.Example1.__init__(self)
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Color(self, r, g, b):
|
def Color(self, r, g, b):
|
||||||
return r
|
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
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,14 @@ if a.pong != "Foo::pong();MyFoo::ping()"
|
||||||
end
|
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
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,7 @@
|
||||||
#define WARN_LANG_DIRECTOR_VDESTRUCT 514
|
#define WARN_LANG_DIRECTOR_VDESTRUCT 514
|
||||||
#define WARN_LANG_DISCARD_CONST 515
|
#define WARN_LANG_DISCARD_CONST 515
|
||||||
#define WARN_LANG_OVERLOAD_IGNORED 516
|
#define WARN_LANG_OVERLOAD_IGNORED 516
|
||||||
|
#define WARN_LANG_DIRECTOR_ABSTRACT 517
|
||||||
|
|
||||||
/* -- Reserved (600-799) -- */
|
/* -- Reserved (600-799) -- */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -248,10 +248,12 @@ int Dispatcher::accessDeclaration(Node *n) { return defaultHandler(n); }
|
||||||
int Dispatcher::usingDeclaration(Node *n) { return defaultHandler(n); }
|
int Dispatcher::usingDeclaration(Node *n) { return defaultHandler(n); }
|
||||||
int Dispatcher::namespaceDeclaration(Node *n) { return defaultHandler(n); }
|
int Dispatcher::namespaceDeclaration(Node *n) { return defaultHandler(n); }
|
||||||
|
|
||||||
|
|
||||||
/* Allocators */
|
/* Allocators */
|
||||||
Language::Language() :
|
Language::Language() :
|
||||||
none_comparison(NewString("$arg != 0")),
|
none_comparison(NewString("$arg != 0")),
|
||||||
director_ctor_code(NewString("")),
|
director_ctor_code(NewString("")),
|
||||||
|
director_prot_ctor_code(0),
|
||||||
symbols(NewHash()),
|
symbols(NewHash()),
|
||||||
classtypes(NewHash()),
|
classtypes(NewHash()),
|
||||||
enumtypes(NewHash()),
|
enumtypes(NewHash()),
|
||||||
|
|
@ -270,6 +272,11 @@ Language::Language() :
|
||||||
" $nondirector_new \n",
|
" $nondirector_new \n",
|
||||||
"}\n", NIL);
|
"}\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() {
|
Language::~Language() {
|
||||||
|
|
@ -1665,7 +1672,7 @@ int Language::classDirectorConstructors(Node *n) {
|
||||||
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
|
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
|
||||||
nodeType = Getattr(ni, "nodeType");
|
nodeType = Getattr(ni, "nodeType");
|
||||||
if (!Cmp(nodeType, "constructor")) {
|
if (!Cmp(nodeType, "constructor")) {
|
||||||
if (is_public(ni)) {
|
if (is_public(ni) || (dirprot_mode() && is_protected(ni))) {
|
||||||
classDirectorConstructor(ni);
|
classDirectorConstructor(ni);
|
||||||
constructor = 1;
|
constructor = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -1960,6 +1967,7 @@ int Language::classHandler(Node *n) {
|
||||||
Iterator k;
|
Iterator k;
|
||||||
int old_mode = cplus_mode;
|
int old_mode = cplus_mode;
|
||||||
cplus_mode = CPLUS_PROTECTED;
|
cplus_mode = CPLUS_PROTECTED;
|
||||||
|
|
||||||
for (k = First(vtable); k.key; k = Next(k)) {
|
for (k = First(vtable); k.key; k = Next(k)) {
|
||||||
item = k.item;
|
item = k.item;
|
||||||
Node *method = Getattr(item, "methodNode");
|
Node *method = Getattr(item, "methodNode");
|
||||||
|
|
@ -2002,9 +2010,22 @@ int Language::constructorDeclaration(Node *n) {
|
||||||
String *symname = Getattr(n,"sym:name");
|
String *symname = Getattr(n,"sym:name");
|
||||||
|
|
||||||
if (!CurrentClass) return SWIG_NOWRAP;
|
if (!CurrentClass) return SWIG_NOWRAP;
|
||||||
if (cplus_mode != CPLUS_PUBLIC) return SWIG_NOWRAP;
|
|
||||||
if (ImportMode) 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 */
|
/* Name adjustment for %name */
|
||||||
Swig_save("constructorDeclaration",n,"sym:name",NIL);
|
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);
|
Swig_require("constructorHandler",n,"?name","*sym:name","?type","?parms",NIL);
|
||||||
String *symname = Getattr(n,"sym:name");
|
String *symname = Getattr(n,"sym:name");
|
||||||
String *mrename = Swig_name_construct(symname);
|
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);
|
Setattr(n,"sym:name", mrename);
|
||||||
functionWrapper(n);
|
functionWrapper(n);
|
||||||
Delete(mrename);
|
Delete(mrename);
|
||||||
|
|
@ -2554,9 +2586,30 @@ String * Language::getClassType() const {
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int Language::abstractClassTest(Node *n) {
|
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) {
|
void Language::setSubclassInstanceCheck(String *nc) {
|
||||||
none_comparison = nc;
|
none_comparison = nc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,18 @@ static File *f_int_to_enum = 0;
|
||||||
class OCAML : public Language {
|
class OCAML : public Language {
|
||||||
public:
|
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 *Swig_class_name(Node *n) {
|
||||||
String *name;
|
String *name;
|
||||||
name = Copy(Getattr(n, "sym:name"));
|
name = Copy(Getattr(n, "sym:name"));
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,20 @@ Python Options (available with -python)\n\
|
||||||
|
|
||||||
class PYTHON : public Language {
|
class PYTHON : public Language {
|
||||||
public:
|
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()
|
* main()
|
||||||
* ------------------------------------------------------------ */
|
* ------------------------------------------------------------ */
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,15 @@ public:
|
||||||
f_init = 0;
|
f_init = 0;
|
||||||
useGlobalModule = false;
|
useGlobalModule = false;
|
||||||
multipleInheritance = 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 *s = NewString("");
|
||||||
String *temp = 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) {
|
switch (current) {
|
||||||
case MEMBER_FUNC:
|
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) {
|
if (multipleInheritance) {
|
||||||
Printv(klass->init, tab4, rb_define_method,"(", klass->mImpl, ", \"",
|
Printv(klass->init, tab4, rb_define_method,"(", klass->mImpl, ", \"",
|
||||||
iname, "\", ", wname, ", -1);\n", NIL);
|
iname, "\", ", wname, ", -1);\n", NIL);
|
||||||
|
|
@ -645,7 +654,7 @@ public:
|
||||||
Replaceall(klass->init,"$allocator", s);
|
Replaceall(klass->init,"$allocator", s);
|
||||||
break;
|
break;
|
||||||
case CONSTRUCTOR_INITIALIZE:
|
case CONSTRUCTOR_INITIALIZE:
|
||||||
Printv(s, tab4, "rb_define_method(", klass->vname,
|
Printv(s, tab4, rb_define_method,"(", klass->vname,
|
||||||
", \"initialize\", ", wname, ", -1);\n", NIL);
|
", \"initialize\", ", wname, ", -1);\n", NIL);
|
||||||
Replaceall(klass->init,"$initializer", s);
|
Replaceall(klass->init,"$initializer", s);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -269,6 +269,9 @@ public:
|
||||||
/* Director constructor "template" code */
|
/* Director constructor "template" code */
|
||||||
String *director_ctor_code;
|
String *director_ctor_code;
|
||||||
|
|
||||||
|
/* Director 'protected' constructor "template" code*/
|
||||||
|
String *director_prot_ctor_code;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Hash *symbols;
|
Hash *symbols;
|
||||||
Hash *classtypes;
|
Hash *classtypes;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue