Home | History | Annotate | Download | only in lua
      1 /* -----------------------------------------------------------------------------
      2  * luatypemaps.swg
      3  *
      4  * basic typemaps for Lua.
      5  * ----------------------------------------------------------------------------- */
      6 
      7 /* -----------------------------------------------------------------------------
      8  *                          standard typemaps
      9  * ----------------------------------------------------------------------------- */
     10 /* NEW LANGUAGE NOTE:
     11    the 'checkfn' param is something that I added for typemap(in)
     12    it is an optional fn call to check the type of the lua object
     13    the fn call must be of the form
     14      int checkfn(lua_State *L, int index);
     15    and return 1/0 depending upon if this is the correct type
     16    For the typemap(out), an additional SWIG_arg parameter must be incremented
     17    to reflect the number of values returned (normally SWIG_arg++; will do)
     18 */
     19 // numbers
     20 %typemap(in,checkfn="lua_isnumber") int, short, long,
     21              signed char, float, double
     22 %{$1 = ($type)lua_tonumber(L, $input);%}
     23 
     24 // additional check for unsigned numbers, to not permit negative input
     25 %typemap(in,checkfn="lua_isnumber") unsigned int,
     26              unsigned short, unsigned long, unsigned char
     27 %{SWIG_contract_assert((lua_tonumber(L,$input)>=0),"number must not be negative")
     28 $1 = ($type)lua_tonumber(L, $input);%}
     29 
     30 %typemap(out) int,short,long,
     31              unsigned int,unsigned short,unsigned long,
     32              signed char,unsigned char,
     33              float,double
     34 %{  lua_pushnumber(L, (lua_Number) $1); SWIG_arg++;%}
     35 
     36 // we must also provide typemaps for primitives by const reference:
     37 // given a function:
     38 //	int intbyref(const int& i);
     39 // SWIG assumes that this code will need a pointer to int to be passed in
     40 // (this might be ok for objects by const ref, but not for numeric primitives)
     41 // therefore we add a set of typemaps to fix this (for both in & out)
     42 %typemap(in,checkfn="lua_isnumber") const int&($basetype temp)
     43 %{ temp=($basetype)lua_tonumber(L,$input); $1=&temp;%}
     44 
     45 %typemap(in,checkfn="lua_isnumber") const unsigned int&($basetype temp)
     46 %{SWIG_contract_assert((lua_tonumber(L,$input)>=0),"number must not be negative")
     47 temp=($basetype)lua_tonumber(L,$input); $1=&temp;%}
     48 
     49 %typemap(out) const int&, const unsigned int&
     50 %{  lua_pushnumber(L, (lua_Number) *$1); SWIG_arg++;%}
     51 
     52 // for the other numbers we can just use an apply statement to cover them
     53 %apply const int & {const short&,const long&,const signed char&,
     54              const float&,const double&};
     55 
     56 %apply const unsigned int & {const unsigned short&,const unsigned long&,
     57              const unsigned char&};
     58 
     59 /* enums have to be handled slightly differently
     60 	VC++ .net will not allow a cast from lua_Number(double) to enum directly.
     61 */
     62 %typemap(in,checkfn="lua_isnumber") enum SWIGTYPE
     63 %{$1 = ($type)(int)lua_tonumber(L, $input);%}
     64 
     65 %typemap(out) enum SWIGTYPE
     66 %{  lua_pushnumber(L, (lua_Number)(int)($1)); SWIG_arg++;%}
     67 
     68 // and const refs
     69 %typemap(in,checkfn="lua_isnumber") const enum SWIGTYPE &($basetype temp)
     70 %{ temp=($basetype)(int)lua_tonumber(L,$input); $1=&temp;%}
     71 %typemap(out) const enum SWIGTYPE &
     72 %{  lua_pushnumber(L, (lua_Number) *$1); SWIG_arg++;%}
     73 
     74 
     75 // boolean (which is a special type in lua)
     76 // note: lua_toboolean() returns 1 or 0
     77 // note: 1 & 0 are not booleans in lua, only true & false
     78 %typemap(in,checkfn="lua_isboolean") bool
     79 %{$1 = (lua_toboolean(L, $input)!=0);%}
     80 
     81 %typemap(out) bool
     82 %{  lua_pushboolean(L,(int)($1!=0)); SWIG_arg++;%}
     83 
     84 // for const bool&, SWIG treats this as a const bool* so we must dereference it
     85 %typemap(in,checkfn="lua_isboolean") const bool& (bool temp)
     86 %{temp=(lua_toboolean(L, $input)!=0);
     87   $1=&temp;%}
     88 
     89 %typemap(out) const bool&
     90 %{  lua_pushboolean(L,(int)((*$1)!=0)); SWIG_arg++;%}
     91 
     92 // strings (char * and char[])
     93 %fragment("SWIG_lua_isnilstring", "header") {
     94 SWIGINTERN int SWIG_lua_isnilstring(lua_State *L, int idx) {
     95   int ret = lua_isstring(L, idx);
     96   if (!ret)
     97    ret = lua_isnil(L, idx);
     98   return ret;
     99 }
    100 }
    101 
    102 %typemap(in,checkfn="SWIG_lua_isnilstring",fragment="SWIG_lua_isnilstring") const char *, char *
    103 %{$1 = ($ltype)lua_tostring(L, $input);%}
    104 
    105 %typemap(in,checkfn="SWIG_lua_isnilstring",fragment="SWIG_lua_isnilstring") const char[ANY], char[ANY]
    106 %{$1 = ($ltype)lua_tostring(L, $input);%}
    107 
    108 %typemap(out) const char *, char *
    109 %{  lua_pushstring(L,(const char *)$1); SWIG_arg++;%}
    110 
    111 %typemap(out) const char[ANY], char[ANY]
    112 %{  lua_pushstring(L,(const char *)$1); SWIG_arg++;%}
    113 
    114 // char's
    115 // currently treating chars as small strings, not as numbers
    116 // (however signed & unsigned char's are numbers...)
    117 %typemap(in,checkfn="SWIG_lua_isnilstring",fragment="SWIG_lua_isnilstring") char
    118 %{$1 = (lua_tostring(L, $input))[0];%}
    119 
    120 %typemap(out) char
    121 %{  lua_pushfstring(L,"%c",$1); SWIG_arg++;%}
    122 
    123 // by const ref
    124 %typemap(in,checkfn="SWIG_lua_isnilstring",fragment="SWIG_lua_isnilstring") const char& (char temp)
    125 %{temp = (lua_tostring(L, $input))[0]; $1=&temp;%}
    126 
    127 %typemap(out) const char&
    128 %{  lua_pushfstring(L,"%c",*$1); SWIG_arg++;%}
    129 
    130 // pointers and references
    131 // under SWIG rules, it is ok, to have a pass in a lua nil,
    132 // it should be converted to a SWIG NULL.
    133 // This will only be allowed for pointers & arrays, not refs or by value
    134 // the checkfn lua_isuserdata will only work for userdata
    135 // the checkfn SWIG_isptrtype will work for both userdata and nil
    136 %typemap(in,checkfn="SWIG_isptrtype") SWIGTYPE*,SWIGTYPE[]
    137 %{
    138   if (!SWIG_IsOK(SWIG_ConvertPtr(L,$input,(void**)&$1,$descriptor,$disown))){
    139     SWIG_fail_ptr("$symname",$argnum,$descriptor);
    140   }
    141 %}
    142 
    143 %typemap(in,checkfn="lua_isuserdata") SWIGTYPE&
    144 %{
    145   if (!SWIG_IsOK(SWIG_ConvertPtr(L,$input,(void**)&$1,$descriptor,$disown))){
    146     SWIG_fail_ptr("$symname",$argnum,$descriptor);
    147   }
    148 %}
    149 
    150 // out is simple
    151 %typemap(out) SWIGTYPE*,SWIGTYPE&
    152 %{SWIG_NewPointerObj(L,$1,$descriptor,$owner); SWIG_arg++; %}
    153 
    154 // dynamic casts
    155 // this uses the SWIG_TypeDynamicCast() which relies on RTTI to find out what the pointer really is
    156 // the we return it as the correct type
    157 %typemap(out) SWIGTYPE *DYNAMIC,
    158               SWIGTYPE &DYNAMIC
    159 {
    160   swig_type_info *ty = SWIG_TypeDynamicCast($1_descriptor, (void **) &$1);
    161   SWIG_NewPointerObj(L,(void*)$1,ty,$owner); SWIG_arg++;
    162 }
    163 
    164 
    165 // passing objects by value
    166 // SWIG_ConvertPtr wants an object pointer (the $&ltype argp)
    167 // then dereferences it to get the object
    168 %typemap(in,checkfn="lua_isuserdata") SWIGTYPE ($&ltype argp)
    169 %{
    170    if (!SWIG_IsOK(SWIG_ConvertPtr(L,$input,(void**)&argp,$&descriptor,0))){
    171      SWIG_fail_ptr("$symname",$argnum,$&descriptor);
    172    }
    173    $1 = *argp;
    174 %}
    175 
    176 // Also needed for object ptrs by const ref
    177 // eg A* const& ref_pointer(A* const& a);
    178 // found in mixed_types.i
    179 %typemap(in,checkfn="lua_isuserdata") SWIGTYPE *const&($*ltype temp)
    180 %{temp=($*ltype)SWIG_MustGetPtr(L,$input,$*descriptor,0,$argnum,"$symname");
    181 $1=($1_ltype)&temp;%}
    182 
    183 %typemap(out) SWIGTYPE *const&
    184 %{SWIG_NewPointerObj(L,*$1,$*descriptor,$owner); SWIG_arg++; %}
    185 
    186 
    187 // DISOWN-ing typemaps
    188 // if you have an object pointer which must be disowned, use this typemap
    189 // eg. for void destroy_foo(Foo* toDie);
    190 // use %apply SWIGTYPE* DISOWN {Foo* toDie};
    191 // you could just use %delobject, but this is more flexible
    192 %typemap(in,checkfn="SWIG_isptrtype") SWIGTYPE* DISOWN,SWIGTYPE DISOWN[]
    193 %{  if (!SWIG_IsOK(SWIG_ConvertPtr(L,$input,(void**)&$1,$descriptor,SWIG_POINTER_DISOWN))){
    194     SWIG_fail_ptr("$symname",$argnum,$descriptor);
    195   }
    196 %}
    197 
    198 
    199 // Primitive types--return by value
    200 // must make a new object, copy the data & return the new object
    201 // Note: the brackets are {...} and not %{..%}, because we want them to be included in the wrapper
    202 // this is because typemap(out) does not support local variables, like in typemap(in) does
    203 // and we need the $&1_ltype resultptr; to be declared
    204 #ifdef __cplusplus
    205 %typemap(out) SWIGTYPE
    206 {
    207   $&1_ltype resultptr = new $1_ltype((const $1_ltype &) $1);
    208   SWIG_NewPointerObj(L,(void *) resultptr,$&1_descriptor,1); SWIG_arg++;
    209 }
    210 #else
    211 %typemap(out) SWIGTYPE
    212 {
    213   $&1_ltype resultptr;
    214   resultptr = ($&1_ltype) malloc(sizeof($1_type));
    215   memmove(resultptr, &$1, sizeof($1_type));
    216   SWIG_NewPointerObj(L,(void *) resultptr,$&1_descriptor,1); SWIG_arg++;
    217 }
    218 #endif
    219 
    220 // member function pointer
    221 // a member fn ptr is not 4 bytes like a normal pointer, but 8 bytes (at least on mingw)
    222 // so the standard wrapping cannot be done
    223 // nor can you cast a member function pointer to a void* (obviously)
    224 // therefore a special wrapping functions SWIG_ConvertMember() & SWIG_NewMemberObj() were written
    225 #ifdef __cplusplus
    226 %typemap(in,checkfn="lua_isuserdata") SWIGTYPE (CLASS::*)
    227 %{
    228   if (!SWIG_IsOK(SWIG_ConvertMember(L,$input,(void*)(&$1),sizeof($type),$descriptor)))
    229     SWIG_fail_ptr("$symname",$argnum,$descriptor);
    230 %}
    231 
    232 %typemap(out) SWIGTYPE (CLASS::*)
    233 %{
    234   SWIG_NewMemberObj(L,(void*)(&$1),sizeof($type),$descriptor); SWIG_arg++;
    235 %}
    236 #endif
    237 
    238 
    239 // void (must be empty without the SWIG_arg++)
    240 %typemap(out) void "";
    241 
    242 /* void* is a special case
    243 A function void fn(void*) should take any kind of pointer as a parameter (just like C/C++ does)
    244 but if its an output, then it should be wrapped like any other SWIG object (using default typemap)
    245 */
    246 %typemap(in,checkfn="SWIG_isptrtype") void*
    247 %{$1=($1_ltype)SWIG_MustGetPtr(L,$input,0,0,$argnum,"$symname");%}
    248 
    249 /* long long is another special case:
    250 as lua only supports one numeric type (lua_Number), we will just
    251 cast it to that & accept the loss of precision.
    252 An alternative solution would be a long long struct or class
    253 with the relevant operators.
    254 */
    255 %apply long {long long, signed long long, unsigned long long};
    256 %apply const long& {const long long&, const signed long long&, const unsigned long long&};
    257 
    258 /* It is possible to also pass a lua_State* into a function, so
    259 void fn(int a, float b, lua_State* s) is wrappable as
    260 > fn(1,4.3) -- note: the state is implicitly passed in
    261 */
    262 %typemap(in, numinputs=0) lua_State*
    263 %{$1 = L;%}
    264 
    265 
    266 
    267 /* -----------------------------------------------------------------------------
    268  *                          typecheck rules
    269  * ----------------------------------------------------------------------------- */
    270 /* These are needed for the overloaded functions
    271 These define the detection routines which will spot what
    272 parameters match which function
    273 */
    274 
    275 // unfortunately lua only considers one type of number
    276 // so all numbers (int,float,double) match
    277 // you could add an advanced fn to get type & check if its integral
    278 %typecheck(SWIG_TYPECHECK_INTEGER)
    279 	 int, short, long,
    280  	 unsigned int, unsigned short, unsigned long,
    281 	 signed char, unsigned char,
    282 	 long long, unsigned long long, signed long long,
    283 	 const int &, const short &, const long &,
    284  	 const unsigned int &, const unsigned short &, const unsigned long &,
    285 	 const signed char&, const unsigned char&,
    286 	 const long long &, const unsigned long long &,
    287 	 enum SWIGTYPE,	const enum SWIGTYPE&,
    288 	 float, double, const float &, const double&
    289 {
    290   $1 = lua_isnumber(L,$input);
    291 }
    292 
    293 %typecheck(SWIG_TYPECHECK_BOOL)
    294     bool, const bool &
    295 {
    296   $1 = lua_isboolean(L,$input);
    297 }
    298 
    299 // special check for a char (string of length 1)
    300 %typecheck(SWIG_TYPECHECK_CHAR,fragment="SWIG_lua_isnilstring") char, const char& {
    301   $1 = SWIG_lua_isnilstring(L,$input) && (lua_rawlen(L,$input)==1);
    302 }
    303 
    304 %typecheck(SWIG_TYPECHECK_STRING,fragment="SWIG_lua_isnilstring") char *, char[] {
    305   $1 = SWIG_lua_isnilstring(L,$input);
    306 }
    307 
    308 %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE [] {
    309   void *ptr;
    310   if (SWIG_isptrtype(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $1_descriptor, 0)) {
    311     $1 = 0;
    312   } else {
    313     $1 = 1;
    314   }
    315 }
    316 
    317 %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE & {
    318   void *ptr;
    319   if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $1_descriptor, 0)) {
    320     $1 = 0;
    321   } else {
    322     $1 = 1;
    323   }
    324 }
    325 
    326 %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE {
    327   void *ptr;
    328   if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $&1_descriptor, 0)) {
    329     $1 = 0;
    330   } else {
    331     $1 = 1;
    332   }
    333 }
    334 
    335 %typecheck(SWIG_TYPECHECK_VOIDPTR) void * {
    336   void *ptr;
    337   if (SWIG_isptrtype(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, 0, 0)) {
    338     $1 = 0;
    339   } else {
    340     $1 = 1;
    341   }
    342 }
    343 
    344 // Also needed for object pointers by const ref
    345 // eg const A* ref_pointer(A* const& a);
    346 // found in mixed_types.i
    347 %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *const&
    348 {
    349   void *ptr;
    350   if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $*descriptor, 0)) {
    351     $1 = 0;
    352   } else {
    353     $1 = 1;
    354   }
    355 }
    356 
    357 /* -----------------------------------------------------------------------------
    358  *                          Others
    359  * ----------------------------------------------------------------------------- */
    360 
    361 // Array reference typemaps
    362 %apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) }
    363 
    364 /* const pointers */
    365 %apply SWIGTYPE * { SWIGTYPE *const }
    366 
    367 // size_t (which is just a unsigned long)
    368 %apply unsigned long { size_t };
    369 %apply const unsigned long & { const size_t & };
    370 
    371 
    372 /* -----------------------------------------------------------------------------
    373  *                          Specials
    374  * ----------------------------------------------------------------------------- */
    375 // swig::LANGUAGE_OBJ was added to allow containers of native objects
    376 // however its rather difficult to do this in lua, as you cannot hold pointers
    377 // to native objects (they are held in the interpreter)
    378 // therefore for now: just ignoring this feature
    379 #ifdef __cplusplus
    380 %ignore swig::LANGUAGE_OBJ;
    381 
    382 //%inline %{
    383 %{
    384 namespace swig {
    385 typedef struct{} LANGUAGE_OBJ;
    386 }
    387 %}
    388 
    389 #endif // __cplusplus
    390