Fixes to support protected members with director, proper virtual member recognition and support of the nodirector feature

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@5485 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2003-12-05 01:59:28 +00:00
commit 75c1713b2d
13 changed files with 380 additions and 37 deletions

View file

@ -1,5 +1,57 @@
Version 1.3.20 (In progress)
============================
12/04/2003: mmatus (Marcelo Matus)
- Now the virtual members with no explicit declarator
are properly identified:
struct A {
virtual int f() = 0;
};
struct B {
int f();
};
Here, B::f() is virtual, and the director and the
virtual elimination mechanism now recognize that.
- Initial support for protected virtual methods. They are now
properly emitted when using with director (python only by
now).
%feature("director") A;
struct A {
protected:
virtual int f1() = 0;
};
%feature("director") B;
struct B : A{
protected:
int f1();
virtual f2();
};
This can be dissabled by using the '-nodirprot' option.
- The feature 'nodirector' is working now at the top level,
so, it must work for all the languages:
%feature("director") A;
%feature("nodirector") A::f2;
struct A {
virtual int f1();
virtual int f2();
};
in this case, only 'f1' is exported to the director class.
- Added director support for const TYPE& arguments (python).
12/02/2003: cheetah (William Fulton)
[Java] Fix for INOUT and OUTPUT typemaps in typemaps.i for when the JNI type
is bigger than the C type. For example, unsigned long (32bits on most systems)

View file

@ -112,6 +112,8 @@ CPP_TEST_CASES += \
director_basic \
director_exception \
director_finalizer \
director_nested \
director_protected \
director_unroll \
director_wombat \
dynamic_cast \

View file

@ -0,0 +1,62 @@
%module(directors="1") director_nested
%{
#include <string>
#include <iostream>
%}
%include "std_string.i"
%feature("director") FooBar<int>;
%newobject *::create();
%inline %{
template <class C>
class Foo {
public:
virtual ~Foo() {}
std::string advance()
{
return "Foo::advance;" + do_advance();
}
protected:
virtual std::string do_advance() = 0;
};
%}
%template(Foo_int) Foo<int>;
%inline %{
class Bar : public Foo<int>
{
public:
std::string step()
{
return "Bar::step;" + advance();
}
protected:
std::string do_advance()
{
return "Bar::do_advance;" + do_step();
}
virtual std::string do_step() = 0;
};
template <class C>
class FooBar : public Bar
{
public:
virtual C get_value() = 0;
};
%}
%template(FooBar_int) FooBar<int>;

View file

@ -0,0 +1,46 @@
%module(directors="1") director_protected
%{
#include <string>
#include <iostream>
%}
%include "std_string.i"
%feature("director") Foo;
%feature("director") Bar;
%newobject *::create();
%inline %{
class Foo {
public:
virtual ~Foo() {}
virtual std::string pong() {
return "Foo::pong();" + ping();
}
protected:
virtual std::string ping() = 0;
};
class Bar : public Foo
{
public:
Foo* create()
{
return new Bar();
}
std::string pong() {
return "Bar::pong();" + Foo::pong();
}
protected:
std::string ping() {
return "Bar::ping();";
};
};
%}

View file

@ -0,0 +1,36 @@
from director_nested import *
class A(FooBar_int):
def do_step(self):
return "A::do_step;"
def get_value(self):
return "A::get_value"
pass
a = A()
if a.step() != "Bar::step;Foo::advance;Bar::do_advance;A::do_step;":
raise RuntimeError,"Bad A virtual resolution"
class B(FooBar_int):
def do_advance(self):
return "B::do_advance;" + self.do_step()
def do_step(self):
return "B::do_step;"
def get_value(self):
return "B::get_value"
pass
b = B()
if b.step() != "Bar::step;Foo::advance;B::do_advance;B::do_step;":
raise RuntimeError,"Bad B virtual resolution"

View file

@ -0,0 +1,54 @@
from director_protected import *
class FooBar(Bar):
def ping(self):
return "FooBar::ping();"
b = Bar()
f = b.create()
fb = FooBar()
try:
s1 = b.pong()
if s1 != "Bar::pong();Foo::pong();Bar::ping();":
raise RuntimeError
pass
except:
raise RuntimeError, "bad Bar::pong"
try:
s2 = f.pong()
if s2 != "Bar::pong();Foo::pong();Bar::ping();":
raise RuntimeError
pass
except:
raise RuntimeError," bad Foo::pong"
try:
s3 = fb.pong()
if s3 != "Bar::pong();Foo::pong();FooBar::ping();":
raise RuntimeError
pass
except:
raise RuntimeError," bad FooBar::pong"
private=1
try:
b.ping()
private=0
except:
pass
if not private:
raise RuntimeError,"Boo::ping is private"
private=1
try:
f.ping()
private=0
except:
pass
if not private:
raise RuntimeError,"Foo::ping is private"

View file

@ -440,12 +440,33 @@
%typemap(directorin,parse="i") bool "";
%typemap(directorin,parse="i") enum SWIGTYPE "";
%typemap(directorin,parse="l") unsigned int, unsigned short, unsigned long, unsigned char "(long) $1_name";
%typemap(directorin,parse="l") unsigned int, unsigned short,
unsigned long, unsigned char "(long) $1_name";
%typemap(directorin) long long
"$input = PyLong_FromLongLong($1_name);";
%typemap(directorin) unsigned long long
"$input = PyLong_FromUnsignedLongLong($1_name);";
%typemap(directorin) long long
"$input = PyLong_FromLongLong($1_name);";
%typemap(directorin) unsigned long long
"$input = PyLong_FromUnsignedLongLong($1_name);";
%typemap(directorin,parse="i") const int& "";
%typemap(directorin,parse="h") const short& "";
%typemap(directorin,parse="l") const long& "";
%typemap(directorin,parse="b") const signed char& "";
%typemap(directorin,parse="f") const float& "";
%typemap(directorin,parse="d") const double& "";
%typemap(directorin,parse="i") const bool& "";
%typemap(directorin,parse="l") const unsigned int&,
const unsigned short&, const unsigned long&,
const unsigned char& "(long) $1_name";
%typemap(directorin) const long long&
"$input = PyLong_FromLongLong($1_name);";
%typemap(directorin) const unsigned long long&
"$input = PyLong_FromUnsignedLongLong($1_name);";
%typemap(directorin, parse="l") int *DIRECTORIN, long* DIRECTORIN,
unsigned int *DIRECTORIN, unsigned long *DIRECTORIN,
@ -457,7 +478,7 @@
%typemap(directorin, parse="O") PyObject* "";
%typemap(directorin, parse="l") std::size_t "(long) $input";
%typemap(directorin, parse="l") std::size_t, const std::size_t& "(long) $input";
/* // this is rather dangerous
%typemap(directorin) SWIGTYPE {
@ -713,6 +734,7 @@ DIRECTOROUT_TYPEMAP(std::size_t, PyInt_AsLong);
%ignorewarn("362:operator= ignored") operator=;
%ignorewarn("383:operator++ ignored") operator++;
%ignorewarn("384:operator-- ignored") operator--;
%ignorewarn("385:operator! ignored") operator!;
%ignorewarn("381:operator&& ignored") operator&&;
%ignorewarn("382:operator|| ignored") operator||;
%ignorewarn("386:operator->* ignored") operator->*;

View file

@ -308,7 +308,7 @@ static void add_symbols(Node *n) {
}
/* Don't add symbols for private/protected members */
if (inclass && (cplus_mode != CPLUS_PUBLIC)) {
if (inclass && (cplus_mode == CPLUS_PRIVATE)) {
while (n) {
Swig_symbol_add(0, n); /* Add to C symbol table */
if (cplus_mode == CPLUS_PRIVATE) {
@ -327,6 +327,9 @@ static void add_symbols(Node *n) {
n = nextSibling(n);
continue;
}
if (cplus_mode == CPLUS_PROTECTED) {
Setattr(n,"access", "protected");
}
decl = Getattr(n,"decl");
if (!SwigType_isfunction(decl)) {
symname = make_name(Getattr(n,"name"),0);
@ -3506,9 +3509,11 @@ def_args : EQUAL definetype {
Node *n = Swig_symbol_clookup($3.id,0);
if (n) {
String *q = Swig_symbol_qualified(n);
if (Getattr(n,"access")) {
if (cplus_mode == CPLUS_PUBLIC) {
Swig_warning(WARN_PARSE_PRIVATE, cparse_file, cparse_line,"'%s' is private in this context.\n", $3.id);
String *a = Getattr(n,"access");
if (a && (Strncmp(a,"private",7) == 0)) {
if (cplus_mode != CPLUS_PRIVATE) {
Swig_warning(WARN_PARSE_PRIVATE, cparse_file,
cparse_line,"'%s' is %s in this context.\n", q, a);
Swig_warning(WARN_PARSE_BAD_DEFAULT, cparse_file, cparse_line,"Can't set default argument value (ignored)\n");
}
$$.val = 0;
@ -4314,7 +4319,9 @@ expr : exprnum { $$ = $1; }
/* Check if value is in scope */
n = Swig_symbol_clookup($1,0);
if (n) {
if (Getattr(n,"access") && (cplus_mode == CPLUS_PUBLIC)) {
String *a = Getattr(n,"access");
if (a && (Strncmp(a, "private", 7) == 0)
&& (cplus_mode != CPLUS_PRIVATE)) {
Swig_warning(WARN_PARSE_PRIVATE,cparse_file, cparse_line, "'%s' is private in this context.\n", $1);
$$.type = T_ERROR;
} else {

View file

@ -19,6 +19,7 @@
char cvsroot_allocate_cxx[] = "$Header$";
#include "swigmod.h"
#include "utils.h"
static int virtual_elimination_mode = 0; /* set to 0 on default */
/* Set virtual_elimination_mode */
@ -93,6 +94,7 @@ class Allocate : public Dispatcher {
(checkAttribute(temp, "type", type)) &&
(!Strcmp(local_decl, base_decl)) ) {
// Indicate a virtual method in the derived class, that is, not the virtual method definition in a base class
Setattr(c, "storage", "virtual");
Setattr(c, "virtual:derived", "1");
if (virtual_elimination_mode)
Setattr(c, "feature:ignore", "1");
@ -146,7 +148,8 @@ class Allocate : public Dispatcher {
bases = Getattr(classnode, "bases");
if (!bases) return 0;
if (checkAttribute(member, "storage", "virtual")) {
//if (checkAttribute(member, "storage", "virtual"))
{
if (function_is_defined_in_bases(member, bases))
defined = 1;
}
@ -318,7 +321,7 @@ class Allocate : public Dispatcher {
{
for (int i = 0; i < Len(methods); ) {
Node *n = Getitem(methods,i);
if (checkAttribute(n,"access","protected") || checkAttribute(n,"access","private")) {
if (!is_public(n)) {
Delitem(methods,i);
continue;
}
@ -490,8 +493,8 @@ public:
if (inclass) {
/* check whether the member node n is defined in class node inclass's bases */
if (checkAttribute(n, "storage", "virtual"))
class_member_is_defined_in_bases(n, inclass);
// if (checkAttribute(n, "storage", "virtual"))
class_member_is_defined_in_bases(n, inclass);
/* Check to see if this is a static member or not. If so, we add an attribute
cplus:staticbase that saves the current class */

View file

@ -15,8 +15,17 @@
char cvsroot_lang_cxx[] = "$Header$";
#include "swigmod.h"
#include "utils.h"
#include <ctype.h>
static int director_protected_mode = 0; /* set to 0 on default */
/* Set director_protected_mode */
void Wrapper_director_protected_mode_set(int flag) {
director_protected_mode = flag;
}
/* Some status variables used during parsing */
static int InClass = 0; /* Parsing C++ or not */
@ -689,7 +698,7 @@ int Language::cDeclaration(Node *n) {
SwigType *ty, *fullty;
if (CurrentClass && (cplus_mode != CPLUS_PUBLIC)) return SWIG_NOWRAP;
if (Cmp(storage,"typedef") == 0) {
Swig_save("cDeclaration",n,"type",NIL);
SwigType *t = Copy(type);
@ -1421,27 +1430,27 @@ int Language::unrollVirtualMethods(Node *n,
// find the methods that need directors
classname = Getattr(n, "name");
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
if (!Cmp(Getattr(ni, "feature:nodirector"), "1")) continue;
nodeType = Getattr(ni, "nodeType");
storage = Getattr(ni, "storage");
decl = Getattr(ni, "decl");
if (!Cmp(nodeType, "cdecl") && SwigType_isfunction(decl)) {
int is_virtual = storage && !Cmp(storage, "virtual");
String* access = Getattr(ni, "access");
if (!access || !Cmp(access, "public")) {
if (is_virtual) {
String *method_id;
String *name = Getattr(ni, "name");
method_id = NewStringf("%s|%s", name, decl);
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);
}
if (is_virtual &&
(is_public(ni) || (is_protected(ni) && director_protected_mode))) {
Setattr(ni, "feature:director", "1");
String *method_id;
String *name = Getattr(ni, "name");
method_id = NewStringf("%s|%s", name, decl);
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")) {
@ -1504,8 +1513,7 @@ int Language::classDirectorConstructors(Node *n) {
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
nodeType = Getattr(ni, "nodeType");
if (!Cmp(nodeType, "constructor")) {
String* access = Getattr(ni, "access");
if (!access || !Cmp(access, "public")) {
if (is_public(ni)) {
classDirectorConstructor(ni);
constructor = 1;
}
@ -1637,7 +1645,7 @@ int Language::classDeclaration(Node *n) {
ClassType = NewStringf("%s %s", kind, classname);
}
Setattr(n,"classtype", SwigType_namestr(ClassType));
Setattr(n,"classtypeobj", Copy(ClassType));
InClass = 1;
CurrentClass = n;

View file

@ -12,6 +12,8 @@
char cvsroot_python_cxx[] = "$Header$";
#include "swigmod.h"
#include "utils.h"
#ifndef MACSWIG
#include "swigconfig.h"
@ -68,6 +70,8 @@ Python Options (available with -python)\n\
-noexcept - No automatic exception handling\n\
-noproxy - Don't generate proxy classes \n\n";
extern void Wrapper_director_protected_mode_set(int);
class PYTHON : public Language {
public:
@ -79,6 +83,8 @@ public:
SWIG_library_directory("python");
Wrapper_director_protected_mode_set(1);
for (int i = 1; i < argc; i++) {
if (argv[i]) {
if(strcmp(argv[i],"-interface") == 0) {
@ -122,6 +128,8 @@ public:
classic = 0;
modern = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i],"-nodirprot") == 0) {
Wrapper_director_protected_mode_set(0);
} else if (strcmp(argv[i],"-help") == 0) {
fputs(usage,stderr);
} else if (strcmp (argv[i], "-ldflags") == 0) {
@ -1304,8 +1312,15 @@ public:
/* declare Python return value */
Wrapper_add_local(w, "result", "PyObject *result");
/* direct call to superclass if _up is set */
Printf(w->code, "if (swig_get_up()) {\n");
if (is_protected(n)) {
Printf(w->code, "PyObject *obj = PyObject_GetAttrString(swig_get_self(), \"%s\");\n",
Getattr(n,"sym:name"));
Printf(w->code, "if (!obj) {\n");
} else {
Printf(w->code, "if (swig_get_up()) {\n");
}
if (pure_virtual) {
Printf(w->code, "throw Swig::DirectorPureVirtualException();\n");
} else {

View file

@ -24,6 +24,7 @@
char cvsroot_typepass_cxx[] = "$Header$";
#include "swigmod.h"
#include "utils.h"
struct normal_node {
Symtab *symtab;
@ -799,7 +800,7 @@ public:
ns = 0;
}
if (!ns) {
if (!Getattr(n,"access") || ((Strcmp(Getattr(n,"access"),"public") == 0))) {
if (is_public(n)) {
Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(n), Getline(n), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(n,"uname")));
}
} else {

View file

@ -0,0 +1,35 @@
#ifndef __Modules_utils_h__
#define __Modules_utils_h__
inline
int is_public(Node* n)
{
String* access = Getattr(n, "access");
return !access || !Cmp(access, "public");
}
inline
int is_private(Node* n)
{
String* access = Getattr(n, "access");
return access && !Cmp(access, "private");
}
inline
int is_protected(Node* n)
{
String* access = Getattr(n, "access");
return access && !Cmp(access, "protected");
}
inline
int is_member_director(Node* classnode, Node* member)
{
int class_director = !Cmp(Getattr(classnode,"feature:director"), "1");
int cdecl_nodirector = !Cmp(Getattr(member,"feature:nodirector"),"1");
return class_director && !cdecl_nodirector;
}
#endif //__Modules_utils_h__