swig/Lib/typemaps/implicit.swg
William S Fulton 91aba9f719 UTL STL container descriptor checks
The vector of pointers (just fixed) were not working correctly because the
descriptors returned from swig::type_info() were sometimes returning
zero. Zero should only be used for void * as the subsequent call to
SWIG_ConvertPtr will blindly cast the pointer without checking
descriptor.

std::vector<void *> does not work and will require further changes:
specializing traits_info<void *> to return 0 and traits_asptr<void *>.
I tried this and traits_asptr<void> also needs to be added in which
seems odd and requires further investigation...

Lib/python/pystdcommon.swg:
  template <> struct traits_info<void *> {
    static swig_type_info *type_info() {
      static swig_type_info *info = 0;
    }
  };

Lib/std/std_common.i:
  template <>
  struct traits_asptr<void *> {
    static int asptr(PyObject *obj, void ***val) {
      void **p;
      swig_type_info *descriptor = 0;
      int res = SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0);
      if (SWIG_IsOK(res)) {
	if (val) *val = p;
      }
      return res;
    }
  };

  // this is needed, but am not sure this is expected
  template <>
  struct traits_asptr<void> {
    static int asptr(PyObject *obj, void **val) {
      void **p;
      swig_type_info *descriptor = 0;
      int res = SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0);
      if (SWIG_IsOK(res)) {
	if (val) *val = p;
      }
      return res;
    }
  };
2016-07-28 22:51:29 +01:00

208 lines
4.9 KiB
Text

/*
The %implicit macro allows a SwigType (Class) to be accepted
as an input parameter and use its implicit constructors when needed.
For example:
%implicit(A, int, double, B);
%inline
{
struct B { };
struct A
{
int ii;
A(int i) { ii = 1; }
A(double d) { ii = 2; }
A(const B& b) { ii = 3; }
};
int get(A a) { return a.ii; }
}
Here, you can call 'get' as
get(1) ==> get(A(1))
get(2.0) ==> get(A(2.0))
get(B()) ==> get(A(B()))
and swig will construct an 'A' temporal variable using the
corresponding implicit constructor.
The plain implicit macro takes care of simple type list. If it doesn't
work because you are passing template types with commas, then use
the %implicit_{1,2,3} versions and/or the %arg macro.
*/
%define %implicit_type(Type...)
%traits_swigtype(Type);
%enddef
%define %implicit_frag(Type...) ,fragment=SWIG_Traits_frag(Type) %enddef
%define %implicit_code(Type...)
{
Type _v;
int res = swig::asval<Type >(obj, &_v);
if (SWIG_IsOK(res)) {
if (val) *val = new value_type(static_cast<const Type& >(_v));
return SWIG_AddNewMask(res);
}
}
%enddef
/* implicit */
%define %implicit(Type, ...)
%formacro_1(%implicit_type,__VA_ARGS__);
%fragment(SWIG_Traits_frag(Type),"header",
fragment="StdTraits"
%formacro_1(%implicit_frag,__VA_ARGS__)) %{
namespace swig {
template <> struct traits<Type > {
typedef pointer_category category;
static const char* type_name() { return "Type"; }
};
template <> struct traits_asptr< Type > {
typedef Type value_type;
static int asptr(SWIG_Object obj, value_type **val) {
Type *vptr;
static swig_type_info* descriptor = SWIG_TypeQuery("Type *");
int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&vptr, descriptor, 0) : SWIG_ERROR;
if (SWIG_IsOK(res)) {
if (val) *val = vptr;
return res;
} else {
%formacro_1(%implicit_code,__VA_ARGS__)
}
return SWIG_TypeError;
}
};
}
%}
%typemap_traits_ptr(%checkcode(POINTER),Type);
%enddef
/* implicit_1 */
%define %implicit_1(Type, Imp1)
%traits_swigtype(Imp1);
%fragment(SWIG_Traits_frag(Type),"header",
fragment="StdTraits",
fragment=SWIG_Traits_frag(Imp1)) %{
namespace swig {
template <> struct traits< Type > {
typedef pointer_category category;
static const char* type_name() { return "Type"; }
};
template <> struct traits_asptr< Type > {
typedef Type value_type;
static int asptr(SWIG_Object obj, value_type **val) {
Type *vptr;
static swig_type_info* descriptor = SWIG_TypeQuery("Type *");
int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&vptr, descriptor, 0) : SWIG_ERROR;
if (SWIG_IsOK(res)) {
if (val) *val = vptr;
return res;
} else {
%implicit_code(Imp1);
}
return SWIG_TypeError;
}
};
}
%}
%typemap_traits_ptr(%checkcode(POINTER),Type);
%enddef
/* implicit_2 */
%define %implicit_2(Type, Imp1, Imp2)
%traits_swigtype(Imp1);
%traits_swigtype(Imp2);
%fragment(SWIG_Traits_frag(Type),"header",
fragment="StdTraits",
fragment=SWIG_Traits_frag(Imp1),
fragment=SWIG_Traits_frag(Imp2)) %{
namespace swig {
template <> struct traits< Type > {
typedef pointer_category category;
static const char* type_name() { return "Type"; }
};
template <> struct traits_asptr< Type > {
typedef Type value_type;
static int asptr(SWIG_Object obj, value_type **val) {
Type *vptr;
static swig_type_info* descriptor = SWIG_TypeQuery("Type *");
int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&vptr, descriptor, 0) : SWIG_ERROR;
if (SWIG_IsOK(res)) {
if (val) *val = vptr;
return SWIG_OLDOBJ;
} else {
%implicit_code(Imp1);
%implicit_code(Imp2);
}
return SWIG_TypeError;
}
};
}
%}
%typemap_traits_ptr(%checkcode(POINTER),Type);
%enddef
/* implicit_3 */
%define %implicit_3(Type, Imp1, Imp2, Imp3)
%traits_swigtype(Imp1);
%traits_swigtype(Imp2);
%traits_swigtype(Imp3);
%fragment(SWIG_Traits_frag(Type),"header",
fragment="StdTraits",
fragment=SWIG_Traits_frag(Imp1),
fragment=SWIG_Traits_frag(Imp2),
fragment=SWIG_Traits_frag(Imp3)) %{
namespace swig {
template <> struct traits< Type > {
typedef pointer_category category;
static const char* type_name() { return "Type"; }
};
template <> struct traits_asptr< Type > {
typedef Type value_type;
static int asptr(SWIG_Object obj, value_type **val) {
Type *vptr;
static swig_type_info* descriptor = SWIG_TypeQuery("Type *");
int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&vptr, descriptor, 0) : SWIG_ERROR;
if (SWIG_IsOK(res)) {
if (val) *val = vptr;
return res;
} else {
%implicit_code(Imp1);
%implicit_code(Imp2);
%implicit_code(Imp3);
}
return SWIG_TypeError;
}
};
}
%}
%typemap_traits_ptr(%checkcode(POINTER),Type);
%enddef