properly manage the strange but valid case:

typedef char namet[5];
  const namet def_namet = {'h','o', 0, 'l','a'};

ie, char arrays with null embedded characters, and other odd
char[ANY] situations.

add the corresponding test to the primitive_types.i and runme files.

Marcelo

 ----------------------------------------------------------------------


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@5685 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2004-01-24 07:20:59 +00:00
commit b3896b1919
4 changed files with 153 additions and 100 deletions

View file

@ -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);

View file

@ -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"

View file

@ -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);
}
}

View file

@ -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);
}
/*****************************************************************************
*