diff --git a/Examples/test-suite/primitive_types.i b/Examples/test-suite/primitive_types.i index c35346aab..492fed210 100644 --- a/Examples/test-suite/primitive_types.i +++ b/Examples/test-suite/primitive_types.i @@ -81,10 +81,17 @@ char name[5]; int val; - MyInt(int v = 0): val(v) { } + MyInt(int v = 0): val(v) { + name[0]='n'; + } operator int() const { return val; } }; + + typedef char namet[5]; + extern namet gbl_namet; + namet gbl_namet; + %} // // adding applies for incomplete swig type MyInt @@ -101,6 +108,7 @@ %apply long { pint }; + // // Some simple types %inline %{ @@ -114,8 +122,10 @@ char* const def_pchar = "hello"; - const namet def_namet = "hola";//{'h','o','l','a',0}; + const namet def_namet = {'h','o',0, 'l','a'}; + extern namet gbl_namet; + %} @@ -305,15 +315,20 @@ macro(MyInt, pfx, myint) %test_prim_types_int(ovr_decl, ovr); - const char* stringl(const char *str, size_t len) + int strlen(const char *str, size_t len) { - return str; + return len; } - int main(size_t argc, const char **argv) + int mainc(size_t argc, const char **argv) { return argc; } + + const char* mainv(size_t argc, const char **argv, int idx) + { + return argv[idx]; + } }; @@ -327,6 +342,7 @@ macro(MyInt, pfx, myint) virtual ~TestDirector() { + var_namet[0]='h'; } %test_prim_types_int(stc_decl, stc); diff --git a/Examples/test-suite/python/primitive_types_runme.py b/Examples/test-suite/python/primitive_types_runme.py index 0976525a3..60c378638 100644 --- a/Examples/test-suite/python/primitive_types_runme.py +++ b/Examples/test-suite/python/primitive_types_runme.py @@ -31,26 +31,26 @@ def pyerror(name, val, cte): raise RuntimeError pass -if cvar.var_bool != cct_bool: pyerror("bool", var_bool, cct_bool) -if cvar.var_schar != cct_schar: pyerror("schar", var_schar, cct_schar) -if cvar.var_uchar != cct_uchar: pyerror("uchar", var_uchar, cct_uchar) -if cvar.var_int != cct_int: pyerror("int", var_int, cct_int) -if cvar.var_uint != cct_uint: pyerror("uint", var_uint, cct_uint) -if cvar.var_short != cct_short: pyerror("short", var_short, cct_short) -if cvar.var_ushort != cct_ushort: pyerror("ushort", var_ushort, cct_ushort) -if cvar.var_long != cct_long: pyerror("long", var_long, cct_long) -if cvar.var_ulong != cct_ulong: pyerror("ulong", var_ulong, cct_ulong) -if cvar.var_llong != cct_llong: pyerror("llong", var_llong, cct_llong) -if cvar.var_ullong != cct_ullong: pyerror("ullong", var_ullong, cct_ullong) -if cvar.var_float != cct_float: pyerror("float", var_float, cct_float) -if cvar.var_double != cct_double: pyerror("double", var_double, cct_double) -if cvar.var_char != cct_char: pyerror("char", var_char, cct_char) -if cvar.var_pchar != cct_pchar: pyerror("pchar", var_pchar, cct_pchar) -if cvar.var_pint != cct_pint: pyerror("pint", var_pint, cct_pint) -if cvar.var_sizet != cct_sizet: pyerror("sizet", var_sizet, cct_sizet) -if cvar.var_hello != cct_hello: pyerror("hello", var_hello, cct_hello) -if cvar.var_myint != cct_myint: pyerror("myint", var_myint, cct_myint) -if cvar.var_namet != def_namet: pyerror("name", var_namet, def_namet) +if cvar.var_bool != cct_bool: pyerror("bool", cvar.var_bool, cct_bool) +if cvar.var_schar != cct_schar: pyerror("schar", cvar.var_schar, cct_schar) +if cvar.var_uchar != cct_uchar: pyerror("uchar", cvar.var_uchar, cct_uchar) +if cvar.var_int != cct_int: pyerror("int", cvar.var_int, cct_int) +if cvar.var_uint != cct_uint: pyerror("uint", cvar.var_uint, cct_uint) +if cvar.var_short != cct_short: pyerror("short", cvar.var_short, cct_short) +if cvar.var_ushort != cct_ushort: pyerror("ushort", cvar.var_ushort, cct_ushort) +if cvar.var_long != cct_long: pyerror("long", cvar.var_long, cct_long) +if cvar.var_ulong != cct_ulong: pyerror("ulong", cvar.var_ulong, cct_ulong) +if cvar.var_llong != cct_llong: pyerror("llong", cvar.var_llong, cct_llong) +if cvar.var_ullong != cct_ullong: pyerror("ullong", cvar.var_ullong, cct_ullong) +if cvar.var_float != cct_float: pyerror("float", cvar.var_float, cct_float) +if cvar.var_double != cct_double: pyerror("double", cvar.var_double, cct_double) +if cvar.var_char != cct_char: pyerror("char", cvar.var_char, cct_char) +if cvar.var_pchar != cct_pchar: pyerror("pchar", cvar.var_pchar, cct_pchar) +if cvar.var_pint != cct_pint: pyerror("pint", cvar.var_pint, cct_pint) +if cvar.var_sizet != cct_sizet: pyerror("sizet", cvar.var_sizet, cct_sizet) +if cvar.var_hello != cct_hello: pyerror("hello", cvar.var_hello, cct_hello) +if cvar.var_myint != cct_myint: pyerror("myint", cvar.var_myint, cct_myint) +if cvar.var_namet != def_namet: pyerror("name", cvar.var_namet, def_namet) class PyTest (TestDirector): def __init__(self): @@ -157,10 +157,36 @@ t.var_namet = def_namet t.v_check() -if def_namet != 'hola': - raise RuntimeError, "bad namet" +# this value contains a '0' char! +if def_namet != 'ho\0la': + print "bad namet", def_namet + raise RuntimeError + +t.var_namet = def_namet +if t.var_namet != def_namet: + print "bad namet", t.var_namet + raise RuntimeError t.var_namet = 'holac' if t.var_namet != 'holac': - raise RuntimeError, "bad namet" + print "bad namet", t.var_namet + raise RuntimeError + +t.var_namet = 'hol' + +if t.var_namet != 'hol': + print "bad namet", t.var_namet + raise RuntimeError + +largs=['hi','hola','hello'] +if t.mainc(largs) != 3: + raise RuntimeError, "bad main typemap" + +targs=('hi','hola') +if t.mainv(targs,1) != 'hola': + raise RuntimeError, "bad main typemap" + + +if t.strlen('hile') != 4: + raise RuntimeError, "bad string typemap" diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index ddc9cbd01..7896a4bbd 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -170,22 +170,37 @@ SPyObj_FromCharPtr(const char* cptr) { return cptr ? PyString_FromString(cptr) : Py_BuildValue((char*)""); } +/* + these two routines allows char[ANY] with '0' chars inside, ie: + + const char def_namet[5] = {'h','o',0, 'l','a'}; + + is not truncated to "ho". + */ + SWIG_STATIC_INLINE PyObject * -SPyObj_FromCharArray(const char* carray, size_t size) { - return PyString_FromStringAndSize(carray, strnlen(carray, size)); +SPyObj_FromCharArray(const char* carray, int len) { + /* checking the effective size backward */ + for (; len && (carray[len - 1] == 0); --len); + + return PyString_FromStringAndSize(carray, len); } - SWIG_STATIC_INLINE void -SPyObj_AsCharArray(PyObject *obj, char* carray, size_t size) { - const char* s = PyString_Check(obj) ? PyString_AsString(obj) : 0; +SPyObj_AsCharArray(PyObject *obj, char* carray, int size) { + int len = size; + char* buf; + PyString_AsStringAndSize(obj, &buf, &len); if (!PyErr_Occurred()) { - size_t len = strlen(s); if (len > size) { PyErr_SetObject(PyExc_TypeError, - PyString_FromFormat("a string of maximum size %d is required", size)); + PyString_FromFormat("a string of maximum size %d is required", size)); + } else { + memcpy(carray, buf, len); + /* pad the string with zero chars if needed */ + if (len < size) + memset(carray + len, 0, size - len); } - strncpy(carray, s, size); } } diff --git a/Lib/python/python.swg b/Lib/python/python.swg index 4e3963eec..231f40117 100644 --- a/Lib/python/python.swg +++ b/Lib/python/python.swg @@ -21,6 +21,21 @@ #define %shadow %insert("shadow") #define %pythoncode %insert("python") + +/* auxiliar macros for char array alloc/dealloc */ +#ifdef __cplusplus +%define %swig_new_carray(size) new char[(size)] +%enddef +%define %swig_del_carray(cptr) delete [] cptr; +%enddef +#else +%define %swig_new_carray(size) malloc((size)) +%enddef +%define %swig_del_carray(cptr) free((char*)cptr); +%enddef +#endif + + /* ----------------------------------------------------------------------------- * standard typemaps * ----------------------------------------------------------------------------- */ @@ -62,6 +77,23 @@ %enddef +/* ----------------------------------------------------------------------------- + * --- memberin and globalin typemaps --- + * ----------------------------------------------------------------------------- */ + +/* Character array handling */ + +%typemap(memberin) char [ANY] { + if ($input) memcpy($1,$input,$1_dim0); + else memset($1,0,$1_dim0); +} + +%typemap(globalin) char [ANY] { + if ($input) memcpy($1,$input,$1_dim0); + else memset($1,0,$1_dim0); +} + + /* ----------------------------------------------------------------------------- * --- Input arguments --- * ----------------------------------------------------------------------------- */ @@ -190,17 +222,15 @@ %expand_primitives_as(PY_VARIN_TYPEMAP); -/* A string */ -#ifdef __cplusplus - +/* A strings */ %typemap(varin) char * { char *temp = (char *) PyString_AsString($input); if (PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "C variable '$name ($1_ltype)'"); return 1; } - if ($1) delete [] $1; - $1 = ($type) new char[strlen(temp)+1]; + if ($1) %swig_del_carray($1); + $1 = ($type) %swig_new_carray(strlen(temp)+1); strcpy((char*)$1,temp); } @@ -210,34 +240,21 @@ PyErr_SetString(PyExc_TypeError, "C variable '$name ($1_ltype)'"); return 1; } - $1 = ($type) new char[strlen(temp)+1]; + $1 = ($type) %swig_new_carray(strlen(temp)+1); strcpy((char*)$1,temp); } -#else -%typemap(varin) char * { - char *temp = (char *) PyString_AsString($input); +/* here we need no temp, the variable provide the memory */ +%typemap(varin) char [ANY] { + SPyObj_AsCharArray($input, $1, $1_dim0); if (PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "C variable '$name ($1_ltype)'"); return 1; } - if ($1) free((char*) $1); - $1 = ($type) malloc(strlen(temp)+1); - strcpy((char*)$1,temp); } -%typemap(varin,warning="451:Setting const char * variable may leak memory") const char * { - char *temp = (char *) PyString_AsString($input); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "C variable '$name ($1_ltype)'"); - return 1; - } - $1 = ($type) malloc(strlen(temp)+1); - strcpy((char*)$1,temp); -} - -#endif +/* Pointers, references, and arrays */ %typemap(varin) SWIGTYPE [ANY] { void *temp; @@ -251,23 +268,6 @@ for (ii = 0; ii < $1_size; ii++) b[ii] = *(($1_basetype *) temp + ii); } -/* Special case for string array variables */ -%typemap(varin) char* { - $1 = PyString_AsString($input); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "C variable '$name ($1_ltype)'"); - return 1; - } -} - -%typemap(varin) char [ANY] { - SPyObj_AsCharArray($input, $1, $1_dim0); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "C variable '$name ($1_ltype)'"); - return 1; - } -} - %typemap(varin) SWIGTYPE * { void *temp; if ((SWIG_ConvertPtr($input,(void **) &temp, $1_descriptor, SWIG_POINTER_EXCEPTION | SWIG_POINTER_DISOWN)) == -1) { @@ -361,7 +361,7 @@ { SWIG_PY_STRING, (char*)"$symname", 0, 0, (void *)$value, 0} %typemap(consttab) char [ANY], const char [ANY] - { SWIG_PY_STRING, (char*)"$symname", 0, 0, (void *)$value, 0} + "PyDict_SetItemString(d,\"$symname\", SPyObj_FromCharArray($value, $value_dim0));"; %typemap(consttab) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] { SWIG_PY_POINTER, (char*)"$symname", 0, 0, (void *)$value, &$1_descriptor} @@ -426,11 +426,12 @@ } } -%typemap(directorout) char [ANY] { - SPyObj_AsCharArray($input, $result, $result_dim0); +%typemap(directorout) char [ANY] (char temp[$result_dim0]) { + SPyObj_AsCharArray($input, temp, $result_dim0); if (PyErr_Occurred()) { - Swig::DirectorTypeMismatchException("Error converting Python object into char[ANY]"); + Swig::DirectorTypeMismatchException("Error converting Python object into char[$result_dim0]"); } + $result = temp; } /* Object returned by value. Convert from a pointer */ @@ -623,40 +624,35 @@ PY_TYPECHECK_TYPEMAP(CHAR, char, SPyObj_AsChar); /* ------------------------------------------------------------ * --- Argc & Argv --- * ------------------------------------------------------------ */ - +/* This typemap works with either a list or a tuple */ %typemap(in) (int ARGC, char **ARGV) { /* Check if is a list */ - if (PyList_Check($input)) { + int list = PyList_Check($input); + if (list || PyTuple_Check($input)) { int i = 0; - int size = PyList_Size($input); + int size = list ? PyList_Size($input) : PyTuple_Size($input); $1 = ($1_ltype) size; -#ifdef __cplusplus - $2 = ($2_ltype) new char*[(size + 1)]; -#else - $2 = ($2_ltype) malloc((size + 1)*sizeof(char *)); -#endif + $2 = ($2_ltype) %swig_new_carray((size + 1)*sizeof(char*)); for (; i < size; ++i) { - PyObject *o = PyList_GetItem($input,i); - if (PyString_Check(o)) - $2[i] = PyString_AsString(PyList_GetItem($input,i)); - else { - PyErr_SetString(PyExc_TypeError,"list must contain strings"); + PyObject *obj = list ? + PyList_GetItem($input,i) : PyTuple_GetItem($input,i); + $2[i] = PyString_AsString(obj); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError,"list must contain strings only"); SWIG_fail; } } $2[i] = 0; } else { - PyErr_SetString(PyExc_TypeError,"argument is not a python list"); + PyErr_SetString(PyExc_TypeError,"argument is not a python list or tuple"); SWIG_fail; } } -#ifdef __cplusplus -%typemap(freearg) (int ARGC, char **ARGV) "if ($2) delete[] $2;"; -#else -%typemap(freearg) (int ARGC, char **ARGV) "if ($2) free((char *) $2);"; -#endif - +%typemap(freearg) (int ARGC, char **ARGV) { + if ($2) %swig_del_carray($2); +} + /***************************************************************************** *