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:
parent
c600268775
commit
114c703acd
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>
|
||||
|
||||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) -- */
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
* ------------------------------------------------------------ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue