Better mapping of char[ANY] in python, including embedded

null chars, which are allowed in C++ and python, and proper
sizes:

  you can use a shorter string to assign a char[6]:

     x = "he\0l"  -> x := {'h','e',0,'l',0, 0}

  but you always get back in python the original size:

   x := {'h','i','0','0',0, 0} -> "hi\0\0\0\0"

Better mapping of (char*)0, now you get a None in the python
side, and using None, you get a (char*)0, just like
all the other C++ pointers. Before (char*)0 was mapped
into python as "", or as seg. faults.

Better mapping of "", which is not None nor (char*)0.

Added more tests using primitive types with simple templates.


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@5687 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2004-01-25 09:45:18 +00:00
commit 839f109a81
4 changed files with 298 additions and 87 deletions

View file

@ -56,6 +56,26 @@
%apply int { enum SWIGTYPE };
Also note that this test should not only compile, if you run the
program
grep 'resultobj = SWIG_NewPointerObj' primitive_types_wrap.cxx
you should get only two calls:
resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Test, 1);
resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_TestDirector, 1);
if you get a lot more, some typemap could be not defined.
The same with
grep SWIG_ConvertPtr primitive_types_wrap.cxx| egrep -v 'Test'
you should only get
#define SWIG_ConvertPtr(obj, pp, type, flags)
*/
//
@ -63,8 +83,8 @@
// these nowarn flags.
//
#pragma SWIG nowarn=451
#pragma SWIG nowarn=515
#pragma SWIG nowarn=509
//#pragma SWIG nowarn=515
//#pragma SWIG nowarn=509
%{
#include <stddef.h>
@ -74,20 +94,32 @@
%feature("director") TestDirector;
// Fake integer class, only visible in C++
%{
// Integer class, only visible in C++
struct MyInt
{
char name[5];
int val;
MyInt(int v = 0): val(v) {
name[0]='n';
}
operator int() const { return val; }
};
// Template primitive type, only visible in C++
template <class T>
struct Param
{
char name[5];
T val;
Param(T v = 0): val(v) {
}
operator T() const { return val; }
};
typedef char namet[5];
extern namet gbl_namet;
namet gbl_namet;
@ -98,6 +130,14 @@
//
%apply int { MyInt };
%apply const int& { const MyInt& };
%apply int { Param<int> };
%apply char { Param<char> };
%apply float { Param<float> };
%apply double { Param<double> };
%apply const int& { const Param<int>& };
%apply const char& { const Param<char>& };
%apply const float& { const Param<float>& };
%apply const double& { const Param<double>& };
@ -107,6 +147,7 @@
%apply const int& { const Hello& };
%apply long { pint };
%apply const long& { const pint& };
//
@ -118,9 +159,11 @@
typedef char namet[5];
typedef char* pchar;
typedef const char* pcharc;
typedef int* pint;
char* const def_pchar = "hello";
const char* const def_pcharc = "hija";
const namet def_namet = {'h','o',0, 'l','a'};
@ -148,9 +191,12 @@
#define def_sizet 1
#define def_hello Hola
#define def_myint 1
#define def_parami 1
#define def_paramd 1
#define def_paramc 'c'
%define %test_prim_types_int(macro, pfx)
/* all the primitive types */
/* types that can be declared as static const class members */
%define %test_prim_types_stc(macro, pfx)
macro(bool, pfx, bool)
macro(signed char, pfx, schar)
macro(unsigned char, pfx, uchar)
@ -168,14 +214,24 @@ macro(char, pfx, char)
%enddef
%define %test_prim_types(macro, pfx)
%test_prim_types_int(macro, pfx)
/* types that can be used to test overloading */
%define %test_prim_types_ovr(macro, pfx)
%test_prim_types_stc(macro, pfx)
macro(pchar, pfx, pchar)
%enddef
/* all the types */
%define %test_prim_types(macro, pfx)
%test_prim_types_ovr(macro, pfx)
macro(pcharc, pfx, pcharc)
macro(pint, pfx, pint)
/* these ones should behave like primitive types too */
macro(size_t, pfx, sizet)
macro(Hello, pfx, hello)
macro(MyInt, pfx, myint)
macro(Param<int>, pfx, parami)
macro(Param<double>, pfx, paramd)
macro(Param<char>, pfx, paramc)
macro(size_t, pfx, sizet)
%enddef
@ -191,8 +247,6 @@ macro(MyInt, pfx, myint)
/* C++ constant declaration */
%define cct_decl(type, pfx, name)
const type pfx##_##name = def##_##name;
const type* pfx##_##name##_p = &pfx##_##name;
const type& pfx##_##name##_r = pfx##_##name;
%enddef
/* C++ static constant declaration */
@ -233,6 +287,7 @@ macro(MyInt, pfx, myint)
void var_init()
{
var_pchar = 0;
var_pcharc = 0;
var_pint = 0;
var_namet[0] = 'h';
}
@ -255,9 +310,10 @@ macro(MyInt, pfx, myint)
/* check a function call */
%define call_check(type, pfx, name)
if (pfx##_##name(def_##name) != def_##name) {
type pfx##_##tmp##name = def_##name;
if (pfx##_##name(pfx##_##tmp##name) != def_##name) {
std::ostringstream a; std::ostringstream b;
a << pfx##_##name(def_##name);
a << pfx##_##name(pfx##_##tmp##name);
b << def_##name;
if (a.str() != b.str()) {
std::cout << "failing in pfx""_""name : "
@ -275,10 +331,11 @@ macro(MyInt, pfx, myint)
/* function passing by value */
%define ovr_decl(type, pfx, name)
int pfx##_##val(type x) { return 1; }
int pfx##_##ref(const type& x) { return 1; }
virtual int pfx##_##val(type x) { return 1; }
virtual int pfx##_##ref(const type& x) { return 1; }
%enddef
#ifdef SWIGPYTHON
%apply (char *STRING, int LENGTH) { (const char *str, size_t len) }
%apply (int ARGC, char **ARGV) { (size_t argc, const char **argv) }
@ -288,13 +345,34 @@ macro(MyInt, pfx, myint)
struct Test
{
Test()
: var_pchar(0), var_pint(0)
: var_pchar(0), var_pcharc(0), var_pint(0)
{
}
%test_prim_types_int(stc_decl, stc);
%test_prim_types_stc(stc_decl, stc);
%test_prim_types(var_decl, var);
var_decl(namet, var, namet);
const char* val_namet(namet x) throw(namet)
{
return x;
}
const char* val_cnamet(const namet x) throw(namet)
{
return x;
}
#if 0
/* I have no idea how to define a typemap for
const namet&, where namet is a char[ANY] array */
const namet& ref_namet(const namet& x) throw(namet)
{
return x;
}
#endif
%test_prim_types(val_decl, val);
%test_prim_types(ref_decl, ref);
@ -307,13 +385,13 @@ macro(MyInt, pfx, myint)
int v_check()
{
%test_prim_types_int(var_check, stc);
%test_prim_types_stc(var_check, stc);
%test_prim_types(var_check, var);
var_check(namet, var, namet);
return 1;
}
%test_prim_types_int(ovr_decl, ovr);
%test_prim_types_ovr(ovr_decl, ovr);
int strlen(const char *str, size_t len)
{
@ -328,24 +406,44 @@ macro(MyInt, pfx, myint)
const char* mainv(size_t argc, const char **argv, int idx)
{
return argv[idx];
}
}
};
struct TestDirector
{
TestDirector()
: var_pchar(0), var_pint(0)
: var_pchar(0), var_pcharc(0), var_pint(0)
{
}
virtual ~TestDirector()
{
var_namet[0]='h';
}
%test_prim_types_int(stc_decl, stc);
virtual const char* vval_namet(namet x) throw(namet)
{
return x;
}
virtual const char* vval_cnamet(const namet x) throw(namet)
{
return x;
}
#if 0
/* I have no idea how to define a typemap for
const namet&, where namet is a char[ANY] array */
virtual const namet& vref_namet(const namet& x) throw(namet)
{
return x;
}
#endif
%test_prim_types_stc(stc_decl, stc);
%test_prim_types(var_decl, var);
var_decl(namet, var, namet);
@ -367,13 +465,12 @@ macro(MyInt, pfx, myint)
int v_check()
{
%test_prim_types_int(var_check, stc);
%test_prim_types_stc(var_check, stc);
%test_prim_types(var_check, var);
return 1;
}
%test_prim_types_int(ovr_decl, ovr);
%test_prim_types_ovr(ovr_decl, ovr);
};

View file

@ -18,11 +18,15 @@ cvar.var_float = sct_float
cvar.var_double = sct_double
cvar.var_char = sct_char
cvar.var_pchar = sct_pchar
cvar.var_pcharc = sct_pcharc
cvar.var_pint = sct_pint
cvar.var_sizet = sct_sizet
cvar.var_hello = sct_hello
cvar.var_myint = sct_myint
cvar.var_namet = def_namet
cvar.var_parami = sct_parami
cvar.var_paramd = sct_paramd
cvar.var_paramc = sct_paramc
v_check()
@ -46,6 +50,7 @@ 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_pcharc != cct_pcharc: pyerror("pchar", cvar.var_pcharc, cct_pcharc)
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)
@ -74,6 +79,7 @@ class PyTest (TestDirector):
def vval_double(self, x): return self.ident(x)
def vval_char(self, x): return self.ident(x)
def vval_pchar(self, x): return self.ident(x)
def vval_pcharc(self, x): return self.ident(x)
def vval_pint(self, x): return self.ident(x)
def vval_sizet(self, x): return self.ident(x)
def vval_hello(self, x): return self.ident(x)
@ -94,6 +100,7 @@ class PyTest (TestDirector):
def vref_double(self, x): return self.ident(x)
def vref_char(self, x): return self.ident(x)
def vref_pchar(self, x): return self.ident(x)
def vref_pcharc(self, x): return self.ident(x)
def vref_pint(self, x): return self.ident(x)
def vref_sizet(self, x): return self.ident(x)
def vref_hello(self, x): return self.ident(x)
@ -125,11 +132,15 @@ p.var_float = p.stc_float
p.var_double = p.stc_double
p.var_char = p.stc_char
p.var_pchar = sct_pchar
p.var_pcharc = sct_pcharc
p.var_pint = sct_pint
p.var_sizet = sct_sizet
p.var_hello = sct_hello
p.var_myint = sct_myint
p.var_namet = def_namet
p.var_parami = sct_parami
p.var_paramd = sct_paramd
p.var_paramc = sct_paramc
p.v_check()
@ -149,11 +160,15 @@ t.var_float = t.stc_float
t.var_double = t.stc_double
t.var_char = t.stc_char
t.var_pchar = sct_pchar
t.var_pcharc = sct_pcharc
t.var_pint = sct_pint
t.var_sizet = sct_sizet
t.var_hello = sct_hello
t.var_myint = sct_myint
t.var_namet = def_namet
t.var_parami = sct_parami
t.var_paramd = sct_paramd
t.var_paramc = sct_paramc
t.v_check()
@ -175,7 +190,7 @@ if t.var_namet != 'holac':
t.var_namet = 'hol'
if t.var_namet != 'hol':
if t.var_namet != 'hol\0\0':
print "bad namet", t.var_namet
raise RuntimeError
@ -190,3 +205,40 @@ if t.mainv(targs,1) != 'hola':
if t.strlen('hile') != 4:
raise RuntimeError, "bad string typemap"
cvar.var_char = '\0'
if cvar.var_char != '\0':
raise RuntimeError, "bad char '0' case"
cvar.var_char = 0
if cvar.var_char != '\0':
raise RuntimeError, "bad char '0' case"
cvar.var_namet = '\0'
if cvar.var_namet != '\0\0\0\0\0':
raise RuntimeError, "bad char '\0' case"
cvar.var_namet = ''
if cvar.var_namet != '\0\0\0\0\0':
raise RuntimeError, "bad char empty case"
cvar.var_pchar = None
if cvar.var_pchar != None:
raise RuntimeError, "bad None case"
cvar.var_pchar = ''
if cvar.var_pchar != '':
raise RuntimeError, "bad char empty case"
cvar.var_pcharc = None
if cvar.var_pcharc != None:
raise RuntimeError, "bad None case"
cvar.var_pcharc = ''
if cvar.var_pcharc != '':
raise RuntimeError, "bad char empty case"