Better vector/C++ containers support for Scilab

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2012-scilab@13719 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Vincent Couvert 2012-08-24 15:06:40 +00:00
commit 6138b43d7b
8 changed files with 243 additions and 71 deletions

View file

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* scicontainer.swg * scicontainer.swg
* *
* Scilab cell <-> C++ container wrapper (Basd on Octave version) * Scilab list <-> C++ container wrapper (Based on Octave wrapper)
* *
* This wrapper, and its iterator, allows a general use (and reuse) of * This wrapper, and its iterator, allows a general use (and reuse) of
* the mapping between C++ and Scilab, thanks to the C++ templates. * the mapping between C++ and Scilab, thanks to the C++ templates.
@ -24,7 +24,7 @@
%include <sciiterators.swg> %include <sciiterators.swg>
// The Octave C++ Wrap // The Scilab C++ Wrap
%insert(header) %{ %insert(header) %{
#include <stdexcept> #include <stdexcept>
@ -74,8 +74,8 @@ namespace std {
bool bool
operator()(const SciObject& v, const SciObject& w) const operator()(const SciObject& v, const SciObject& w) const
{ {
SciObject res = do_binary_op(SciObject::op_le,v,w); //SciObject res = do_binary_op(SciObject::op_le,v,w);
return res.is_true(); return true;//res.is_true();
} }
}; };
} }
@ -191,7 +191,7 @@ namespace swig {
namespace swig namespace swig
{ {
template <class T> template <class T>
struct SciSequence_Ref // * octave can't support these, because of how assignment works struct SciSequence_Ref // * Scilab can't support these, because of how assignment works
{ {
SciSequence_Ref(const SciObject& seq, int index) SciSequence_Ref(const SciObject& seq, int index)
: _seq(seq), _index(index) : _seq(seq), _index(index)
@ -489,7 +489,7 @@ namespace swig
#endif //SWIG_EXPORT_ITERATOR_METHODS #endif //SWIG_EXPORT_ITERATOR_METHODS
%enddef %enddef
// The octave container methods // The Scilab container methods
%define %swig_container_methods(Container...) %define %swig_container_methods(Container...)
%enddef %enddef
@ -543,15 +543,15 @@ namespace swig
namespace swig { namespace swig {
template <class SciSeq, class Seq> template <class SciSeq, class Seq>
inline void inline void
assign(const SciSeq& octseq, Seq* seq) { assign(const SciSeq& sciseq, Seq* seq) {
%#ifdef SWIG_STD_NOASSIGN_STL %#ifdef SWIG_STD_NOASSIGN_STL
typedef typename SciSeq::value_type value_type; typedef typename SciSeq::value_type value_type;
typename SciSeq::const_iterator it = octseq.begin(); typename SciSeq::const_iterator it = sciseq.begin();
for (;it != octseq.end(); ++it) { for (;it != sciseq.end(); ++it) {
seq->insert(seq->end(),(value_type)(*it)); seq->insert(seq->end(),(value_type)(*it));
} }
%#else %#else
seq->assign(octseq.begin(), octseq.end()); seq->assign(sciseq.begin(), sciseq.end());
%#endif %#endif
} }
@ -570,18 +570,18 @@ namespace swig {
} }
} else if (obj.is_cell()) { } else if (obj.is_cell()) {
try { try {
SciSequence_Cont<value_type> octseq(obj); SciSequence_Cont<value_type> sciseq(obj);
if (seq) { if (seq) {
sequence *pseq = new sequence(); sequence *pseq = new sequence();
assign(octseq, pseq); assign(sciseq, pseq);
*seq = pseq; *seq = pseq;
return SWIG_NEWOBJ; return SWIG_NEWOBJ;
} else { } else {
return octseq.check() ? SWIG_OK : SWIG_ERROR; return sciseq.check() ? SWIG_OK : SWIG_ERROR;
} }
} catch (std::exception& e) { } catch (std::exception& e) {
if (seq&&!error_state) if (seq&&!error_state)
Scierror(999, "swig type error: %s",e.what()); error("swig type error: %s",e.what());
return SWIG_ERROR; return SWIG_ERROR;
} }
} }
@ -597,7 +597,7 @@ namespace swig {
typedef typename sequence::const_iterator const_iterator; typedef typename sequence::const_iterator const_iterator;
static SciObject from(const sequence& seq) { static SciObject from(const sequence& seq) {
#ifdef SWIG_OCTAVE_EXTRA_NATIVE_CONTAINERS #ifdef SWIG_SCILAB_EXTRA_NATIVE_CONTAINERS
swig_type_info *desc = swig::type_info<sequence>(); swig_type_info *desc = swig::type_info<sequence>();
if (desc && desc->clientdata) { if (desc && desc->clientdata) {
return SWIG_NewPointerObj(new sequence(seq), desc, SWIG_POINTER_OWN); return SWIG_NewPointerObj(new sequence(seq), desc, SWIG_POINTER_OWN);
@ -613,7 +613,7 @@ namespace swig {
} }
return c; return c;
} else { } else {
Scierror(999, "swig overflow error: sequence size not valid in Scilab"); error("swig overflow error: sequence size not valid in Scilab");
return SciObject(); return SciObject();
} }
return SciObject(); return SciObject();

View file

@ -296,7 +296,7 @@ namespace swig
struct stop_iteration {}; struct stop_iteration {};
%typemap(throws) stop_iteration { %typemap(throws) stop_iteration {
Scierror(999, "stop_iteration exception"); error("stop_iteration exception");
SWIG_fail; SWIG_fail;
} }

View file

@ -26,3 +26,10 @@ static void SWIG_Scilab_SetOutputPosition(int _outputPosition) {
#define Scilab_Error_Occurred() 0 #define Scilab_Error_Occurred() 0
#define SWIG_Scilab_AddErrorMsg(msg) {;} #define SWIG_Scilab_AddErrorMsg(msg) {;}
namespace std {
class SciObject {
public:
SciObject();
};
}

View file

@ -1,14 +1,10 @@
// Based on Python implementation
%fragment("StdTraits","header",fragment="StdTraitsCommon") %fragment("StdTraits","header",fragment="StdTraitsCommon")
{ {
namespace swig { namespace swig {
/* // Traits that provides the from method
Traits that provides the from method
*/
template <class Type> struct traits_from_ptr { template <class Type> struct traits_from_ptr {
static SciObject from(Type *val, int owner = 0) { static SciObject from(Type *val, int owner = 0) {
return SWIG_InternalNewPointerObj(val, type_info<Type>(), owner); return 0; //SWIG_NewPointerObj(val, type_info<Type>(), owner);
} }
}; };
@ -41,29 +37,27 @@ namespace swig {
return traits_from_ptr<Type>::from(val, owner); return traits_from_ptr<Type>::from(val, owner);
} }
/* // Traits that provides the asval/as/check method
Traits that provides the asval/as/check method
*/
template <class Type> template <class Type>
struct traits_asptr { struct traits_asptr {
static int asptr(SciObject obj, Type **val) { static int asptr(const SciObject& obj, Type **val) {
Type *p; Type *p;
int res = SWIG_ConvertPtr(obj, (void**)&p, type_info<Type>(), 0); int res = SWIG_ConvertPtr(obj, (void**)&p, type_info<Type>(), 0);
if (SWIG_IsOK(res)) { if (SWIG_IsOK(res)) {
if (val) *val = p; if (val) *val = p;
} }
return res; return res;
} }
}; };
template <class Type> template <class Type>
inline int asptr(SciObject obj, Type **vptr) { inline int asptr(const SciObject& obj, Type **vptr) {
return traits_asptr<Type>::asptr(obj, vptr); return traits_asptr<Type>::asptr(obj, vptr);
} }
template <class Type> template <class Type>
struct traits_asval { struct traits_asval {
static int asval(SciObject obj, Type *val) { static int asval(const SciObject& obj, Type *val) {
if (val) { if (val) {
Type *p = 0; Type *p = 0;
int res = traits_asptr<Type>::asptr(obj, &p); int res = traits_asptr<Type>::asptr(obj, &p);
@ -86,7 +80,7 @@ namespace swig {
}; };
template <class Type> struct traits_asval<Type*> { template <class Type> struct traits_asval<Type*> {
static int asval(SciObject obj, Type **val) { static int asval(const SciObject& obj, Type **val) {
if (val) { if (val) {
typedef typename noconst_traits<Type>::noconst_type noconst_type; typedef typename noconst_traits<Type>::noconst_type noconst_type;
noconst_type *p = 0; noconst_type *p = 0;
@ -102,30 +96,30 @@ namespace swig {
}; };
template <class Type> template <class Type>
inline int asval(SciObject obj, Type *val) { inline int asval(const SciObject& obj, Type *val) {
return traits_asval<Type>::asval(obj, val); return traits_asval<Type>::asval(obj, val);
} }
template <class Type> template <class Type>
struct traits_as<Type, value_category> { struct traits_as<Type, value_category> {
static Type as(SciObject obj, bool throw_error) { static Type as(const SciObject& obj, bool throw_error) {
Type v; Type v;
int res = asval(obj, &v); int res = asval(obj, &v);
if (!obj || !SWIG_IsOK(res)) { //if (!obj.is_defined() || !SWIG_IsOK(res)) {
// if (!PyErr_Occurred()) { if (!Scilab_Error_Occurred()) {
// ::%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
// } }
if (throw_error) throw std::invalid_argument("bad type"); if (throw_error) throw std::invalid_argument("bad type");
} //}
return v; return v;
} }
}; };
template <class Type> template <class Type>
struct traits_as<Type, pointer_category> { struct traits_as<Type, pointer_category> {
static Type as(SciObject obj, bool throw_error) { static Type as(const SciObject& obj, bool throw_error) {
Type *v = 0; Type *v = 0;
int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR); int res = traits_asptr<Type>::asptr(obj, &v);
if (SWIG_IsOK(res) && v) { if (SWIG_IsOK(res) && v) {
if (SWIG_IsNewObj(res)) { if (SWIG_IsNewObj(res)) {
Type r(*v); Type r(*v);
@ -137,9 +131,9 @@ namespace swig {
} else { } else {
// Uninitialized return value, no Type() constructor required. // Uninitialized return value, no Type() constructor required.
static Type *v_def = (Type*) malloc(sizeof(Type)); static Type *v_def = (Type*) malloc(sizeof(Type));
// if (!PyErr_Occurred()) { if (!Scilab_Error_Occurred()) {
// %type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
// } }
if (throw_error) throw std::invalid_argument("bad type"); if (throw_error) throw std::invalid_argument("bad type");
memset(v_def,0,sizeof(Type)); memset(v_def,0,sizeof(Type));
return *v_def; return *v_def;
@ -149,15 +143,15 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<Type*, pointer_category> { struct traits_as<Type*, pointer_category> {
static Type* as(SciObject obj, bool throw_error) { static Type* as(const SciObject& obj, bool throw_error) {
Type *v = 0; Type *v = 0;
int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR); int res = traits_asptr<Type>::asptr(obj, &v);
if (SWIG_IsOK(res)) { if (SWIG_IsOK(res)) {
return v; return v;
} else { } else {
// if (!PyErr_Occurred()) { if (!Scilab_Error_Occurred()) {
// %type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
// } }
if (throw_error) throw std::invalid_argument("bad type"); if (throw_error) throw std::invalid_argument("bad type");
return 0; return 0;
} }
@ -165,28 +159,28 @@ namespace swig {
}; };
template <class Type> template <class Type>
inline Type as(SciObject obj, bool te = false) { inline Type as(const SciObject& obj, bool te = false) {
return traits_as<Type, typename traits<Type>::category>::as(obj, te); return traits_as<Type, typename traits<Type>::category>::as(obj, te);
} }
template <class Type> template <class Type>
struct traits_check<Type, value_category> { struct traits_check<Type, value_category> {
static bool check(SciObject obj) { static bool check(const SciObject& obj) {
int res = obj ? asval(obj, (Type *)(0)) : SWIG_ERROR; int res = asval(obj, (Type *)(0));
return SWIG_IsOK(res) ? true : false; return SWIG_IsOK(res) ? true : false;
} }
}; };
template <class Type> template <class Type>
struct traits_check<Type, pointer_category> { struct traits_check<Type, pointer_category> {
static bool check(SciObject obj) { static bool check(const SciObject& obj) {
int res = obj ? asptr(obj, (Type **)(0)) : SWIG_ERROR; int res = asptr(obj, (Type **)(0));
return SWIG_IsOK(res) ? true : false; return SWIG_IsOK(res) ? true : false;
} }
}; };
template <class Type> template <class Type>
inline bool check(SciObject obj) { inline bool check(const SciObject& obj) {
return traits_check<Type, typename traits<Type>::category>::check(obj); return traits_check<Type, typename traits<Type>::category>::check(obj);
} }
} }
@ -197,7 +191,7 @@ namespace swig {
namespace swig { namespace swig {
template <> struct traits_asval<Type > { template <> struct traits_asval<Type > {
typedef Type value_type; typedef Type value_type;
static int asval(SciObject obj, value_type *val) { static int asval(const SciObject& obj, value_type *val) {
if (Check(obj)) { if (Check(obj)) {
if (val) *val = As(obj); if (val) *val = As(obj);
return SWIG_OK; return SWIG_OK;
@ -214,7 +208,7 @@ namespace swig {
template <> template <>
struct traits_check<Type, value_category> { struct traits_check<Type, value_category> {
static int check(SciObject obj) { static int check(const SciObject& obj) {
int res = Check(obj); int res = Check(obj);
return obj && res ? res : 0; return obj && res ? res : 0;
} }
@ -229,3 +223,4 @@ namespace swig {
#define specialize_std_deque(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From) #define specialize_std_deque(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From)
#define specialize_std_set(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From) #define specialize_std_set(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From)
#define specialize_std_multiset(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From) #define specialize_std_multiset(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From)

64
Lib/scilab/scivector.i Normal file
View file

@ -0,0 +1,64 @@
/*
Vectors typemaps
*/
// Typemap for input arguments of type const std::vector<double> &
%typecheck(SWIG_TYPECHECK_POINTER)
const std::vector<double> &
{
// TODO
}
%typemap(in)
const std::vector<double> &
(int is_new_object=0, std::vector<double> arrayv)
{
{
SciErr sciErr;
int iRows = 0;
int iCols = 0;
int *piAddrVar = NULL;
double *pdblTmp = NULL;
/* Scilab value must be a double vector */
sciErr = getVarAddressFromPosition(pvApiCtx, $input, &piAddrVar);
if (sciErr.iErr) {
printError(&sciErr, 0);
return SWIG_ERROR;
}
if (isDoubleType(pvApiCtx, piAddrVar) && !isVarComplex(pvApiCtx, piAddrVar)) {
sciErr = getMatrixOfDouble(pvApiCtx, piAddrVar, &iRows, &iCols, &pdblTmp);
if (sciErr.iErr) {
printError(&sciErr, 0);
return SWIG_ERROR;
}
} else {
Scierror(999, _("%s: Wrong type for input argument #%d: A real vector expected.\n"), fname, $input);
return SWIG_ERROR;
}
if ((iRows!=1) && (iCols!=1)) {
Scierror(999, _("%s: Wrong size for input argument #%d: A real vector expected.\n"), fname, $input);
return SWIG_ERROR;
}
/* Copy vector contents into new allocated std::vector<double> */
arrayv = std::vector<double>(iRows*iCols);
$1 = &arrayv;
{
int arr_i = 0;
for (arr_i = 0; arr_i < iRows*iCols; ++arr_i)
arrayv[arr_i] = pdblTmp[arr_i];
}
}
}
%typemap(freearg)
const std::vector<double> &
{
// TODO
}
// Typemap for return values of type std::vector<double>
%typemap(out) std::vector<double>
{
// TODO
}

View file

@ -1,18 +1,15 @@
// Based on Python implementation
%include <std/std_except.i> %include <std/std_except.i>
%include <scistdcommon.swg> %include <scistdcommon.swg>
/*
Generate the traits for a 'primitive' type, such as 'double', // Generate the traits for a 'primitive' type, such as 'double',
for which the SWIG_AsVal and SWIG_From methods are already defined. // for which the SWIG_AsVal and SWIG_From methods are already defined.
*/
%define %traits_ptypen(Type...) %define %traits_ptypen(Type...)
%fragment(SWIG_Traits_frag(Type),"header", %fragment(SWIG_Traits_frag(Type),"header",
fragment=SWIG_AsVal_frag(Type), fragment=SWIG_AsVal_frag(Type),
fragment=SWIG_From_frag(Type), fragment=SWIG_From_frag(Type),
fragment="StdTraits") { fragment="StdTraits") {
namespace swig { namespace swig {
template <> struct traits<Type > { template <> struct traits<Type > {
typedef value_category category; typedef value_category category;
@ -34,8 +31,38 @@ namespace swig {
} }
%enddef %enddef
/* Traits for enums. This is bit of a sneaky trick needed because a generic template specialization of enums
is not possible (unless using template meta-programming which SWIG doesn't support because of the explicit
instantiations required using %template). The STL containers define the 'front' method and the typemap
below is used whenever the front method is wrapped returning an enum. This typemap simply picks up the
standard enum typemap, but additionally drags in a fragment containing the traits_asval and traits_from
required in the generated code for enums. */
%include <std/std_common.i> %define %traits_enum(Type...)
%fragment("SWIG_Traits_enum_"{Type},"header",
fragment=SWIG_AsVal_frag(int),
fragment=SWIG_From_frag(int),
fragment="StdTraits") {
namespace swig {
template <> struct traits_asval<Type > {
typedef Type value_type;
static int asval(SciObject obj, value_type *val) {
return SWIG_AsVal(int)(obj, (int *)val);
}
};
template <> struct traits_from<Type > {
typedef Type value_type;
static SciObject from(const value_type& val) {
return SWIG_From(int)((int)val);
}
};
}
}
%typemap(out, fragment="SWIG_Traits_enum_"{Type}) const enum SWIGTYPE& front %{$typemap(out, const enum SWIGTYPE&)%}
%enddef
%include <std/std_common.i>
// //
// Generates the traits for all the known primitive // Generates the traits for all the known primitive

View file

@ -1,10 +1,88 @@
// Vectors /*
Vectors
%fragment("StdVectorTraits","header") */
%fragment("StdVectorTraits","header",fragment="StdSequenceTraits")
%{ %{
namespace swig {
template <class T>
struct traits_asptr<std::vector<T> > {
static int asptr(SciObject *obj, std::vector<T> **vec) {
return traits_asptr_stdseq<std::vector<T> >::asptr(obj, vec);
}
};
template <class T>
struct traits_from<std::vector<T> > {
static SciObject *from(const std::vector<T>& vec) {
return traits_from_stdseq<std::vector<T> >::from(vec);
}
};
}
%} %}
#define %swig_vector_methods(Type...) %swig_sequence_methods(Type) #define %swig_vector_methods(Type...) %swig_sequence_methods(Type)
#define %swig_vector_methods_val(Type...) %swig_sequence_methods_val(Type); #define %swig_vector_methods_val(Type...) %swig_sequence_methods_val(Type);
// Typemap for input arguments of type const std::vector<double> &
%typecheck(SWIG_TYPECHECK_POINTER)
const std::vector<double> &
{
// TODO
}
%typemap(in)
const std::vector<double> &
(int is_new_object=0, std::vector<double> arrayv)
{
{
SciErr sciErr;
int iRows = 0;
int iCols = 0;
int *piAddrVar = NULL;
double *pdblTmp = NULL;
/* Scilab value must be a double vector */
sciErr = getVarAddressFromPosition(pvApiCtx, $input, &piAddrVar);
if (sciErr.iErr) {
printError(&sciErr, 0);
return SWIG_ERROR;
}
if (isDoubleType(pvApiCtx, piAddrVar) && !isVarComplex(pvApiCtx, piAddrVar)) {
sciErr = getMatrixOfDouble(pvApiCtx, piAddrVar, &iRows, &iCols, &pdblTmp);
if (sciErr.iErr) {
printError(&sciErr, 0);
return SWIG_ERROR;
}
} else {
Scierror(999, _("%s: Wrong type for input argument #%d: A real vector expected.\n"), fname, $input);
return SWIG_ERROR;
}
if ((iRows!=1) && (iCols!=1)) {
Scierror(999, _("%s: Wrong size for input argument #%d: A real vector expected.\n"), fname, $input);
return SWIG_ERROR;
}
/* Copy vector contents into new allocated std::vector<double> */
arrayv = std::vector<double>(iRows*iCols);
$1 = &arrayv;
{
int arr_i = 0;
for (arr_i = 0; arr_i < iRows*iCols; ++arr_i)
arrayv[arr_i] = pdblTmp[arr_i];
}
}
}
%typemap(freearg)
const std::vector<double> &
{
// TODO
}
// Typemap for return values of type std::vector<double>
%typemap(out) std::vector<double>
{
// TODO
}
%include <std/std_vector.i> %include <std/std_vector.i>

View file

@ -207,3 +207,4 @@ do this :
%typemap(in) signed char *INOUT = signed char *OUTPUT; %typemap(in) signed char *INOUT = signed char *OUTPUT;
%typemap(in) float *INOUT = float *OUTPUT; %typemap(in) float *INOUT = float *OUTPUT;
%typemap(in) double *INOUT = double *OUTPUT; %typemap(in) double *INOUT = double *OUTPUT;