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
*
* 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
* the mapping between C++ and Scilab, thanks to the C++ templates.
@ -24,7 +24,7 @@
%include <sciiterators.swg>
// The Octave C++ Wrap
// The Scilab C++ Wrap
%insert(header) %{
#include <stdexcept>
@ -74,8 +74,8 @@ namespace std {
bool
operator()(const SciObject& v, const SciObject& w) const
{
SciObject res = do_binary_op(SciObject::op_le,v,w);
return res.is_true();
//SciObject res = do_binary_op(SciObject::op_le,v,w);
return true;//res.is_true();
}
};
}
@ -191,7 +191,7 @@ namespace swig {
namespace swig
{
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)
: _seq(seq), _index(index)
@ -489,7 +489,7 @@ namespace swig
#endif //SWIG_EXPORT_ITERATOR_METHODS
%enddef
// The octave container methods
// The Scilab container methods
%define %swig_container_methods(Container...)
%enddef
@ -543,15 +543,15 @@ namespace swig
namespace swig {
template <class SciSeq, class Seq>
inline void
assign(const SciSeq& octseq, Seq* seq) {
assign(const SciSeq& sciseq, Seq* seq) {
%#ifdef SWIG_STD_NOASSIGN_STL
typedef typename SciSeq::value_type value_type;
typename SciSeq::const_iterator it = octseq.begin();
for (;it != octseq.end(); ++it) {
typename SciSeq::const_iterator it = sciseq.begin();
for (;it != sciseq.end(); ++it) {
seq->insert(seq->end(),(value_type)(*it));
}
%#else
seq->assign(octseq.begin(), octseq.end());
seq->assign(sciseq.begin(), sciseq.end());
%#endif
}
@ -570,18 +570,18 @@ namespace swig {
}
} else if (obj.is_cell()) {
try {
SciSequence_Cont<value_type> octseq(obj);
SciSequence_Cont<value_type> sciseq(obj);
if (seq) {
sequence *pseq = new sequence();
assign(octseq, pseq);
assign(sciseq, pseq);
*seq = pseq;
return SWIG_NEWOBJ;
} else {
return octseq.check() ? SWIG_OK : SWIG_ERROR;
return sciseq.check() ? SWIG_OK : SWIG_ERROR;
}
} catch (std::exception& e) {
if (seq&&!error_state)
Scierror(999, "swig type error: %s",e.what());
error("swig type error: %s",e.what());
return SWIG_ERROR;
}
}
@ -597,7 +597,7 @@ namespace swig {
typedef typename sequence::const_iterator const_iterator;
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>();
if (desc && desc->clientdata) {
return SWIG_NewPointerObj(new sequence(seq), desc, SWIG_POINTER_OWN);
@ -613,7 +613,7 @@ namespace swig {
}
return c;
} 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();

View file

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

View file

@ -26,3 +26,10 @@ static void SWIG_Scilab_SetOutputPosition(int _outputPosition) {
#define Scilab_Error_Occurred() 0
#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")
{
namespace swig {
/*
Traits that provides the from method
*/
// Traits that provides the from method
template <class Type> struct traits_from_ptr {
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);
}
/*
Traits that provides the asval/as/check method
*/
// Traits that provides the asval/as/check method
template <class Type>
struct traits_asptr {
static int asptr(SciObject obj, Type **val) {
struct traits_asptr {
static int asptr(const SciObject& obj, Type **val) {
Type *p;
int res = SWIG_ConvertPtr(obj, (void**)&p, type_info<Type>(), 0);
if (SWIG_IsOK(res)) {
if (val) *val = p;
if (val) *val = p;
}
return res;
}
};
};
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);
}
template <class Type>
struct traits_asval {
static int asval(SciObject obj, Type *val) {
static int asval(const SciObject& obj, Type *val) {
if (val) {
Type *p = 0;
int res = traits_asptr<Type>::asptr(obj, &p);
@ -86,7 +80,7 @@ namespace swig {
};
template <class Type> struct traits_asval<Type*> {
static int asval(SciObject obj, Type **val) {
static int asval(const SciObject& obj, Type **val) {
if (val) {
typedef typename noconst_traits<Type>::noconst_type noconst_type;
noconst_type *p = 0;
@ -102,30 +96,30 @@ namespace swig {
};
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);
}
template <class Type>
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;
int res = asval(obj, &v);
if (!obj || !SWIG_IsOK(res)) {
// if (!PyErr_Occurred()) {
// ::%type_error(swig::type_name<Type>());
// }
//if (!obj.is_defined() || !SWIG_IsOK(res)) {
if (!Scilab_Error_Occurred()) {
%type_error(swig::type_name<Type>());
}
if (throw_error) throw std::invalid_argument("bad type");
}
//}
return v;
}
};
template <class Type>
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;
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_IsNewObj(res)) {
Type r(*v);
@ -137,9 +131,9 @@ namespace swig {
} else {
// Uninitialized return value, no Type() constructor required.
static Type *v_def = (Type*) malloc(sizeof(Type));
// if (!PyErr_Occurred()) {
// %type_error(swig::type_name<Type>());
// }
if (!Scilab_Error_Occurred()) {
%type_error(swig::type_name<Type>());
}
if (throw_error) throw std::invalid_argument("bad type");
memset(v_def,0,sizeof(Type));
return *v_def;
@ -149,15 +143,15 @@ namespace swig {
template <class Type>
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;
int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR);
int res = traits_asptr<Type>::asptr(obj, &v);
if (SWIG_IsOK(res)) {
return v;
} else {
// if (!PyErr_Occurred()) {
// %type_error(swig::type_name<Type>());
// }
if (!Scilab_Error_Occurred()) {
%type_error(swig::type_name<Type>());
}
if (throw_error) throw std::invalid_argument("bad type");
return 0;
}
@ -165,28 +159,28 @@ namespace swig {
};
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);
}
template <class Type>
struct traits_check<Type, value_category> {
static bool check(SciObject obj) {
int res = obj ? asval(obj, (Type *)(0)) : SWIG_ERROR;
static bool check(const SciObject& obj) {
int res = asval(obj, (Type *)(0));
return SWIG_IsOK(res) ? true : false;
}
};
template <class Type>
struct traits_check<Type, pointer_category> {
static bool check(SciObject obj) {
int res = obj ? asptr(obj, (Type **)(0)) : SWIG_ERROR;
static bool check(const SciObject& obj) {
int res = asptr(obj, (Type **)(0));
return SWIG_IsOK(res) ? true : false;
}
};
template <class Type>
inline bool check(SciObject obj) {
inline bool check(const SciObject& obj) {
return traits_check<Type, typename traits<Type>::category>::check(obj);
}
}
@ -197,7 +191,7 @@ namespace swig {
namespace swig {
template <> struct traits_asval<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 (val) *val = As(obj);
return SWIG_OK;
@ -214,7 +208,7 @@ namespace swig {
template <>
struct traits_check<Type, value_category> {
static int check(SciObject obj) {
static int check(const SciObject& obj) {
int res = Check(obj);
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_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)

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 <scistdcommon.swg>
/*
Generate the traits for a 'primitive' type, such as 'double',
for which the SWIG_AsVal and SWIG_From methods are already defined.
*/
// Generate the traits for a 'primitive' type, such as 'double',
// for which the SWIG_AsVal and SWIG_From methods are already defined.
%define %traits_ptypen(Type...)
%fragment(SWIG_Traits_frag(Type),"header",
fragment=SWIG_AsVal_frag(Type),
fragment=SWIG_From_frag(Type),
fragment="StdTraits") {
fragment=SWIG_AsVal_frag(Type),
fragment=SWIG_From_frag(Type),
fragment="StdTraits") {
namespace swig {
template <> struct traits<Type > {
typedef value_category category;
@ -34,8 +31,38 @@ namespace swig {
}
%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

View file

@ -1,10 +1,88 @@
// Vectors
%fragment("StdVectorTraits","header")
/*
Vectors
*/
%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_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>

View file

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