Complete the Python support for shared_ptr mainly for derived classes. This includes the smartptr feature for overriding the class registration function and shared_ptr typemaps
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10236 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
a85143fe7d
commit
f39242fa92
6 changed files with 124 additions and 12 deletions
|
|
@ -1,9 +1,88 @@
|
||||||
Version 1.3.34 (in progress)
|
Version 1.3.34 (in progress)
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
<<<<<<< .mine
|
||||||
|
02/09/2007: wsfulton
|
||||||
|
[Python] Experimental shared_ptr typemaps added. Usage is the same as the recently
|
||||||
|
added Java and C# shared_ptr typemaps. Two macros are available, although these
|
||||||
|
may well change in a future version:
|
||||||
|
|
||||||
|
For base classes or classes not in an inheritance chain:
|
||||||
|
SWIG_SHARED_PTR(PROXYCLASS, TYPE)
|
||||||
|
For derived classes:
|
||||||
|
SWIG_SHARED_PTR_DERIVED(PROXYCLASS, BASECLASSTYPE, TYPE)
|
||||||
|
|
||||||
|
The PROXYCLASS is the name of the proxy class, but is only required for Java/C#.
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
%include "boost_shared_ptr.i"
|
||||||
|
|
||||||
|
SWIG_SHARED_PTR(Klass, Space::Klass)
|
||||||
|
SWIG_SHARED_PTR_DERIVED(KlassDerived, Space::Klass, Space::KlassDerived)
|
||||||
|
|
||||||
|
namespace Space {
|
||||||
|
struct Klass { ... };
|
||||||
|
struct KlassDerived : Klass { ... };
|
||||||
|
}
|
||||||
|
|
||||||
|
Further details to follow in future documentation, but the following features
|
||||||
|
should be noted:
|
||||||
|
|
||||||
|
- Not restricted to boost::shared_ptr, eg std::tr1::shared_ptr can also be used.
|
||||||
|
- Available typemap groups:
|
||||||
|
(a) Typemaps for shared_ptr passed by value, reference, pointer and pointer
|
||||||
|
reference.
|
||||||
|
- (b) Typemaps for passing by raw value, raw pointer, raw reference, raw pointer
|
||||||
|
reference.
|
||||||
|
- The code being wrapped does not even have to use shared_ptr, SWIG can use
|
||||||
|
shared_ptr as the underlying storage mechanism instead of a raw pointer due to
|
||||||
|
the typemaps in group (b) above.
|
||||||
|
- No array support as shared_ptr does not support arrays.
|
||||||
|
- This works quite differently to the usual SWIG smart pointer support when
|
||||||
|
operator-> is parsed by SWIG:
|
||||||
|
- An additional smart pointer class is not generated reducing code bloat in
|
||||||
|
the wrappers.
|
||||||
|
- Using smart pointers and raw pointers can be mixed seamlessly.
|
||||||
|
- Missing constructors for the smart pointers is no longer a problem and so
|
||||||
|
separate factory type functions do not have to be written and wrapped.
|
||||||
|
- The implicit C++ shared_ptr< derived class > to shared_ptr< base class >
|
||||||
|
cast also works in the target language. This negates the necessity to write
|
||||||
|
an explicit helper cast function providing the upcast which would need
|
||||||
|
calling prior to passing a derived class to a method taking a shared_ptr to
|
||||||
|
a base class.
|
||||||
|
|
||||||
|
02/09/2007: wsfulton
|
||||||
|
[Python] Add support for overriding the class registration function via a new
|
||||||
|
"smartptr" feature. This is a very low level of customisation most users
|
||||||
|
would never need to know. The feature will typically be used for intrusive
|
||||||
|
smart pointers along with additional typemaps. Example usage of the feature:
|
||||||
|
|
||||||
|
%feature("smartptr", noblock=1) Foo { boost::shared_ptr< Foo > }
|
||||||
|
class Foo {};
|
||||||
|
|
||||||
|
The generated Foo_swigregister function will then register boost::shared < Foo >
|
||||||
|
(SWIGTYPE_p_boost__shared_ptrTFoo_t instead of SWIGTYPE_p_Foo) as the underlying
|
||||||
|
type for instantiations of Foo.
|
||||||
|
|
||||||
|
02/09/2008: wsfulton
|
||||||
|
Features now supports the optional 'noblock' attribute for all usage of %feature.
|
||||||
|
When specified, the { } braces are removed from the feature code. This is identical
|
||||||
|
in behaviour to usage of 'noblock' in typemaps and is used when the preprocessor
|
||||||
|
is required to operate on the code in the feature and the enclosing { } braces
|
||||||
|
are not required. Example:
|
||||||
|
|
||||||
|
#define FOO foo
|
||||||
|
%feature("smartptr", noblock="1") { FOO::bar }
|
||||||
|
|
||||||
|
The preprocessor then reduces this as if this had been used instead:
|
||||||
|
|
||||||
|
%feature("smartptr") "foo::bar"
|
||||||
|
|
||||||
|
=======
|
||||||
02/01/2008: olly
|
02/01/2008: olly
|
||||||
[Python] Fix format string bug (SF#1882220).
|
[Python] Fix format string bug (SF#1882220).
|
||||||
|
|
||||||
|
>>>>>>> .r10235
|
||||||
01/31/2008: wsfulton
|
01/31/2008: wsfulton
|
||||||
Additions to the %types directive. Now the conversion / casting code can be
|
Additions to the %types directive. Now the conversion / casting code can be
|
||||||
overridden to some custom code in the %types directive, like so:
|
overridden to some custom code in the %types directive, like so:
|
||||||
|
|
|
||||||
|
|
@ -448,7 +448,7 @@ PySwigObject_dealloc(PyObject *v)
|
||||||
{
|
{
|
||||||
PySwigObject *sobj = (PySwigObject *) v;
|
PySwigObject *sobj = (PySwigObject *) v;
|
||||||
PyObject *next = sobj->next;
|
PyObject *next = sobj->next;
|
||||||
if (sobj->own) {
|
if (sobj->own == SWIG_POINTER_OWN) {
|
||||||
swig_type_info *ty = sobj->ty;
|
swig_type_info *ty = sobj->ty;
|
||||||
PySwigClientData *data = ty ? (PySwigClientData *) ty->clientdata : 0;
|
PySwigClientData *data = ty ? (PySwigClientData *) ty->clientdata : 0;
|
||||||
PyObject *destroy = data ? data->destroy : 0;
|
PyObject *destroy = data ? data->destroy : 0;
|
||||||
|
|
@ -977,7 +977,7 @@ SWIG_Python_GetSwigThis(PyObject *pyobj)
|
||||||
|
|
||||||
SWIGRUNTIME int
|
SWIGRUNTIME int
|
||||||
SWIG_Python_AcquirePtr(PyObject *obj, int own) {
|
SWIG_Python_AcquirePtr(PyObject *obj, int own) {
|
||||||
if (own) {
|
if (own == SWIG_POINTER_OWN) {
|
||||||
PySwigObject *sobj = SWIG_Python_GetSwigThis(obj);
|
PySwigObject *sobj = SWIG_Python_GetSwigThis(obj);
|
||||||
if (sobj) {
|
if (sobj) {
|
||||||
int oldown = sobj->own;
|
int oldown = sobj->own;
|
||||||
|
|
@ -997,6 +997,8 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int
|
||||||
if (ptr) *ptr = 0;
|
if (ptr) *ptr = 0;
|
||||||
return SWIG_OK;
|
return SWIG_OK;
|
||||||
} else {
|
} else {
|
||||||
|
if (own)
|
||||||
|
*own = 0;
|
||||||
PySwigObject *sobj = SWIG_Python_GetSwigThis(obj);
|
PySwigObject *sobj = SWIG_Python_GetSwigThis(obj);
|
||||||
while (sobj) {
|
while (sobj) {
|
||||||
void *vptr = sobj->ptr;
|
void *vptr = sobj->ptr;
|
||||||
|
|
@ -1011,7 +1013,15 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int
|
||||||
if (!tc) {
|
if (!tc) {
|
||||||
sobj = (PySwigObject *)sobj->next;
|
sobj = (PySwigObject *)sobj->next;
|
||||||
} else {
|
} else {
|
||||||
if (ptr) *ptr = SWIG_TypeCast(tc,vptr);
|
if (ptr) {
|
||||||
|
int newmemory = 0;
|
||||||
|
*ptr = SWIG_TypeCast(tc,vptr,&newmemory);
|
||||||
|
if (newmemory == SWIG_CAST_NEW_MEMORY) {
|
||||||
|
assert(own);
|
||||||
|
if (own)
|
||||||
|
*own = *own | SWIG_CAST_NEW_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1021,7 +1031,8 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sobj) {
|
if (sobj) {
|
||||||
if (own) *own = sobj->own;
|
if (own)
|
||||||
|
*own = *own | sobj->own;
|
||||||
if (flags & SWIG_POINTER_DISOWN) {
|
if (flags & SWIG_POINTER_DISOWN) {
|
||||||
sobj->own = 0;
|
sobj->own = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1087,7 +1098,7 @@ SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) {
|
||||||
if (ty) {
|
if (ty) {
|
||||||
swig_cast_info *tc = SWIG_TypeCheck(desc,ty);
|
swig_cast_info *tc = SWIG_TypeCheck(desc,ty);
|
||||||
if (!tc) return SWIG_ERROR;
|
if (!tc) return SWIG_ERROR;
|
||||||
*ptr = SWIG_TypeCast(tc,vptr);
|
*ptr = SWIG_TypeCast(tc,vptr,0);
|
||||||
} else {
|
} else {
|
||||||
*ptr = vptr;
|
*ptr = vptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,12 @@ SWIG_SHARED_PTR_TYPEMAPS(PROXYCLASS, const, TYPE)
|
||||||
%define SWIG_SHARED_PTR_DERIVED(PROXYCLASS, BASECLASSTYPE, TYPE...)
|
%define SWIG_SHARED_PTR_DERIVED(PROXYCLASS, BASECLASSTYPE, TYPE...)
|
||||||
SWIG_SHARED_PTR_TYPEMAPS(PROXYCLASS, , TYPE)
|
SWIG_SHARED_PTR_TYPEMAPS(PROXYCLASS, , TYPE)
|
||||||
SWIG_SHARED_PTR_TYPEMAPS(PROXYCLASS, const, TYPE)
|
SWIG_SHARED_PTR_TYPEMAPS(PROXYCLASS, const, TYPE)
|
||||||
|
%types(SWIG_SHARED_PTR_NAMESPACE::shared_ptr< TYPE > = SWIG_SHARED_PTR_NAMESPACE::shared_ptr< BASECLASSTYPE >) %{
|
||||||
|
*newmemory = SWIG_CAST_NEW_MEMORY;
|
||||||
|
return (void *) new SWIG_SHARED_PTR_NAMESPACE::shared_ptr< BASECLASSTYPE >(*(SWIG_SHARED_PTR_NAMESPACE::shared_ptr< TYPE > *)$from);
|
||||||
|
%}
|
||||||
%extend TYPE {
|
%extend TYPE {
|
||||||
static SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< BASECLASSTYPE > SWIGSharedPtrUpcast(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast) {
|
static SWIG_SHARED_PTR_NAMESPACE::shared_ptr< BASECLASSTYPE > SWIGSharedPtrUpcast(SWIG_SHARED_PTR_NAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast) {
|
||||||
return swigSharedPtrUpcast;
|
return swigSharedPtrUpcast;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
/* Flags for pointer conversions */
|
/* Flags for pointer conversions */
|
||||||
#define SWIG_POINTER_DISOWN 0x1
|
#define SWIG_POINTER_DISOWN 0x1
|
||||||
|
#define SWIG_CAST_NEW_MEMORY 0x2
|
||||||
|
|
||||||
/* Flags for new pointer objects */
|
/* Flags for new pointer objects */
|
||||||
#define SWIG_POINTER_OWN 0x1
|
#define SWIG_POINTER_OWN 0x1
|
||||||
|
|
@ -182,7 +183,7 @@ SWIGINTERNINLINE int SWIG_CheckState(int r) {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void *(*swig_converter_func)(void *);
|
typedef void *(*swig_converter_func)(void *, int *);
|
||||||
typedef struct swig_type_info *(*swig_dycast_func)(void **);
|
typedef struct swig_type_info *(*swig_dycast_func)(void **);
|
||||||
|
|
||||||
/* Structure to store information on one type */
|
/* Structure to store information on one type */
|
||||||
|
|
@ -312,8 +313,8 @@ SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *into) {
|
||||||
Cast a pointer up an inheritance hierarchy
|
Cast a pointer up an inheritance hierarchy
|
||||||
*/
|
*/
|
||||||
SWIGRUNTIMEINLINE void *
|
SWIGRUNTIMEINLINE void *
|
||||||
SWIG_TypeCast(swig_cast_info *ty, void *ptr) {
|
SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
|
||||||
return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr);
|
return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -2661,8 +2661,23 @@ public:
|
||||||
if (shadow) {
|
if (shadow) {
|
||||||
/* Generate a class registration function */
|
/* Generate a class registration function */
|
||||||
{
|
{
|
||||||
SwigType *ct = NewStringf("p.%s", real_classname);
|
String *smartptr = Getattr(n, "feature:smartptr"); // Replace storing a pointer to underlying class with a smart pointer (intended for use with non-intrusive smart pointers)
|
||||||
SwigType_remember(ct);
|
SwigType *smart = 0;
|
||||||
|
if (smartptr) {
|
||||||
|
SwigType *cpt = Swig_cparse_type(smartptr);
|
||||||
|
if (cpt) {
|
||||||
|
smart = SwigType_typedef_resolve_all(cpt);
|
||||||
|
Delete(cpt);
|
||||||
|
} else {
|
||||||
|
// TODO: report line number of where the feature comes from
|
||||||
|
Swig_error(Getfile(n), Getline(n), "Invalid type (%s) in 'smartptr' feature for class %s.\n", smartptr, real_classname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SwigType *ct = Copy(smart ? smart : real_classname);
|
||||||
|
SwigType_add_pointer(ct);
|
||||||
|
SwigType *realct = Copy(real_classname);
|
||||||
|
SwigType_add_pointer(realct);
|
||||||
|
SwigType_remember(realct);
|
||||||
Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL);
|
Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL);
|
||||||
Printv(f_wrappers, ctab4, "PyObject *obj;\n", NIL);
|
Printv(f_wrappers, ctab4, "PyObject *obj;\n", NIL);
|
||||||
if (modernargs) {
|
if (modernargs) {
|
||||||
|
|
@ -2680,8 +2695,10 @@ public:
|
||||||
ctab4, "return SWIG_Py_Void();\n", "}\n\n", NIL);
|
ctab4, "return SWIG_Py_Void();\n", "}\n\n", NIL);
|
||||||
String *cname = NewStringf("%s_swigregister", class_name);
|
String *cname = NewStringf("%s_swigregister", class_name);
|
||||||
add_method(cname, cname, 0);
|
add_method(cname, cname, 0);
|
||||||
|
Delete(smart);
|
||||||
Delete(cname);
|
Delete(cname);
|
||||||
Delete(ct);
|
Delete(ct);
|
||||||
|
Delete(realct);
|
||||||
}
|
}
|
||||||
if (!have_constructor) {
|
if (!have_constructor) {
|
||||||
Printv(f_shadow_file, tab4, "def __init__(self): raise AttributeError, \"No constructor defined\"\n", NIL);
|
Printv(f_shadow_file, tab4, "def __init__(self): raise AttributeError, \"No constructor defined\"\n", NIL);
|
||||||
|
|
|
||||||
|
|
@ -1795,7 +1795,7 @@ void SwigType_inherit_equiv(File *out) {
|
||||||
String *lprefix = SwigType_lstr(prefix, 0);
|
String *lprefix = SwigType_lstr(prefix, 0);
|
||||||
Hash *subhash = Getattr(sub, bk.key);
|
Hash *subhash = Getattr(sub, bk.key);
|
||||||
String *convcode = Getattr(subhash, "convcode");
|
String *convcode = Getattr(subhash, "convcode");
|
||||||
Printf(out, "static void *%s(void *x) {", convname);
|
Printf(out, "static void *%s(void *x, int *newmemory) {", convname);
|
||||||
if (convcode) {
|
if (convcode) {
|
||||||
String *fn = Copy(convcode);
|
String *fn = Copy(convcode);
|
||||||
Replaceall(fn, "$from", "x");
|
Replaceall(fn, "$from", "x");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue