1
/***********************************************************************
4
* This file contains the main typemap code to support Lua modules
6
* Author : Mark Gossage (mark@gossage.cjb.net)
7
************************************************************************/
9
/* -----------------------------------------------------------------------------
10
* Basic inout typemaps
11
* ----------------------------------------------------------------------------- */
13
These provide the basic ability for passing in & out of standard numeric data types
14
(int,long,float,double, etc)
16
The basic code looks like this:
18
%typemap(in,checkfn="lua_isnumber") int *INPUT(int temp), int &INPUT(int temp)
19
%{ temp = (int)lua_tonumber(L,$input);
22
%typemap(in, numinputs=0) int *OUTPUT (int temp)
25
%typemap(argout) int *OUTPUT
26
%{ lua_pushnumber(L, (double) *$1); SWIG_arg++;%}
28
%typemap(in) int *INOUT = int *INPUT;
29
%typemap(argout) int *INOUT = int *OUTPUT;
31
However the code below is a mixture of #defines & such, so nowhere as easy to read
33
To make you code work correctly its not just a matter of %including this file
34
You also have to give SWIG the hints on which to use where
37
extern int add_pointer(int* a1,int* a2); // a1 & a2 are pointer values to be added
38
extern void swap(int* s1, int* s2); // does the swap
40
You will need to either change the argument names
41
extern int add_pointer(int* INPUT,int* INPUT);
43
or provide a %apply statement
45
%apply int* INOUT{ int *s1, int *s2 };
46
// if SWIG sees int* s1, int* s2, assume they are inout params
50
%define SWIG_NUMBER_TYPEMAP(TYPE)
51
%typemap(in,checkfn="lua_isnumber") TYPE *INPUT($*type temp), TYPE &INPUT($*type temp)
52
%{ temp = ($*type)lua_tonumber(L,$input);
54
%typemap(in, numinputs=0) TYPE *OUTPUT ($*type temp)
56
%typemap(argout) TYPE *OUTPUT
57
%{ lua_pushnumber(L, (double) *$1); SWIG_arg++;%}
58
%typemap(in) TYPE *INOUT = TYPE *INPUT;
59
%typemap(argout) TYPE *INOUT = TYPE *OUTPUT;
60
// const version (the $*ltype is the basic number without ptr or const's)
61
%typemap(in,checkfn="lua_isnumber") const TYPE *INPUT($*ltype temp)
62
%{ temp = ($*ltype)lua_tonumber(L,$input);
67
SWIG_NUMBER_TYPEMAP(int); SWIG_NUMBER_TYPEMAP(unsigned int);
68
SWIG_NUMBER_TYPEMAP(short); SWIG_NUMBER_TYPEMAP(unsigned short);
69
SWIG_NUMBER_TYPEMAP(long); SWIG_NUMBER_TYPEMAP(unsigned long);
70
SWIG_NUMBER_TYPEMAP(float);
71
SWIG_NUMBER_TYPEMAP(double);
72
SWIG_NUMBER_TYPEMAP(enum SWIGTYPE);
73
// note we dont do char, as a char* is probably a string not a ptr to a single char
75
/* -----------------------------------------------------------------------------
76
* Basic Array typemaps
77
* ----------------------------------------------------------------------------- */
79
I have no idea why this kind of code does not exist in SWIG as standard,
81
This code will convert to/from 1D numeric arrays.
82
In order to reduce code bloat, there are a few macros
83
and quite a few functions defined
84
(unfortunately this makes it a lot less clear)
86
assuming we have functions
87
void process_array(int arr[3]); // nice fixed size array
88
void process_var_array(float arr[],int len); // variable sized array
89
void process_var_array_inout(double arr*,int len); // variable sized array
90
// data passed in & out
91
void process_enum_inout_array_var(enum Days *arrinout, int len); // using enums
92
void return_array_5(int arrout[5]); // out array only
94
in order to wrap them correctly requires a typemap
96
// inform SWIG of the correct typemap
97
// For fixed length, you must specify it as <type> INPUT[ANY]
98
%apply (int INPUT[ANY]) {(int arr[3])};
99
// variable length arrays are just the same
100
%apply (float INPUT[],int) {(float arr[],int len)};
101
// it is also ok, to map the TYPE* instead of a TYPE[]
102
%apply (double *INOUT,int) {(double arr*,int len)};
103
// for the enum's you must use enum SWIGTYPE
104
%apply (enum SWIGTYPE *INOUT,int) {(enum Days *arrinout, int len)};
105
// fixed length out if also fine
106
%apply (int OUTPUT[ANY]) {(int arrout[5])};
108
Generally, you could use %typemap(...)=...
109
but the %apply is neater & easier
111
a few things of note:
112
* all Lua tables are indexed from 1, all C/C++ arrays are indexed from 0
113
therefore t={6,5,3} -- t[1]==6, t[2]==5, t[3]==3
114
when passed to process_array(int arr[3]) becomes
115
arr[0]==6, arr[1]==5, arr[2]==3
116
* for OUTPUT arrays, no array need be passed in, the fn will return a Lua table
117
so for the above mentioned return_array_5() would look like
118
arr=return_array_5() -- no parameters passed in
119
* for INOUT arrays, a table must be passed in, and a new table will be returned
120
(this is consistant with the way that numbers are processed
123
arr=process_var_array_inout(arr) -- arr is replaced by the new version
125
The following are not yet supported:
126
* variable length output only array (inout's work ok)
127
* multidimentional arrays
128
* arrays of objects/structs
134
The internals of the array managment stuff
136
SWIG_ALLOC_ARRAY(TYPE,LEN) // returns a typed array TYPE[LEN]
137
SWIG_FREE_ARRAY(PTR) // delete the ptr (if not zero)
139
// counts the specified table & gets the size
141
int SWIG_itable_size(lua_State* L, int index);
143
int SWIG_table_size(lua_State* L, int index);
145
SWIG_DECLARE_TYPEMAP_ARR_FN(NAME,TYPE)
146
// this fn declares up 4 functions for helping to read/write tables
147
// these can then be called by the macros ...
148
// all assume the table is an integer indexes from 1
149
// but the C array is a indexed from 0
150
// created a fixed size array, reads the specified table
151
// and then fills the array with numbers
152
// returns ptr to the array if ok, or 0 for error
153
// (also pushes a error message to the stack)
154
TYPE* SWIG_get_NAME_num_array_fixed(lua_State* L, int index, int size);
155
// as per SWIG_get_NAME_num_array_fixed()
156
// but reads the entire table & creates an array of the correct size
157
// (if the table is empty, it returns an error rather than a zero length array)
158
TYPE* SWIG_get_NAME_num_array_var(lua_State* L, int index, int* size);
159
// writes a table to Lua with all the specified numbers
160
void SWIG_write_NAME_num_array(lua_State* L,TYPE *array,int size);
161
// read the specified table, and fills the array with numbers
162
// returns 1 of ok (only fails if it doesnt find numbers)
163
// helper fn (called by SWIG_get_NAME_num_array_*() fns)
164
int SWIG_read_NAME_num_array(lua_State* L,int index,TYPE *array,int size);
169
#ifdef __cplusplus /* generic alloc/dealloc fns*/
170
#define SWIG_ALLOC_ARRAY(TYPE,LEN) new (TYPE)[LEN]
171
#define SWIG_FREE_ARRAY(PTR) if(PTR){delete[] PTR;}
173
#define SWIG_ALLOC_ARRAY(TYPE,LEN) (TYPE *)malloc(LEN*sizeof(TYPE))
174
#define SWIG_FREE_ARRAY(PTR) if(PTR){free(PTR);}
177
/* counting the size of arrays:*/
178
int SWIG_itable_size(lua_State* L, int index)
182
lua_rawgeti(L,index,n+1);
183
if (lua_isnil(L,-1))break;
191
int SWIG_table_size(lua_State* L, int index)
194
lua_pushnil(L); /* first key*/
195
while (lua_next(L, index) != 0) {
197
lua_pop(L, 1); /* removes `value'; keeps `key' for next iteration*/
202
/* super macro to declare array typemap helper fns */
203
#define SWIG_DECLARE_TYPEMAP_ARR_FN(NAME,TYPE)\
204
int SWIG_read_##NAME##_num_array(lua_State* L,int index,TYPE *array,int size){\
206
for (i = 0; i < size; i++) {\
207
lua_rawgeti(L,index,i+1);\
208
if (lua_isnumber(L,-1)){\
209
array[i] = (TYPE)lua_tonumber(L,-1);\
218
static TYPE* SWIG_get_##NAME##_num_array_fixed(lua_State* L, int index, int size){\
220
if (!lua_istable(L,index) || SWIG_itable_size(L,index) != size) {\
221
lua_pushfstring(L,"expected a table of size %d",size);\
224
array=SWIG_ALLOC_ARRAY(TYPE,size);\
225
if (!SWIG_read_##NAME##_num_array(L,index,array,size)){\
226
lua_pushstring(L,"table must contain numbers");\
227
SWIG_FREE_ARRAY(array);\
232
static TYPE* SWIG_get_##NAME##_num_array_var(lua_State* L, int index, int* size)\
235
if (!lua_istable(L,index)) {\
236
lua_pushstring(L,"expected a table");\
239
*size=SWIG_itable_size(L,index);\
241
lua_pushstring(L,"table appears to be empty");\
244
array=SWIG_ALLOC_ARRAY(TYPE,*size);\
245
if (!SWIG_read_##NAME##_num_array(L,index,array,*size)){\
246
lua_pushstring(L,"table must contain numbers");\
247
SWIG_FREE_ARRAY(array);\
252
void SWIG_write_##NAME##_num_array(lua_State* L,TYPE *array,int size){\
255
for (i = 0; i < size; i++){\
256
lua_pushnumber(L,(double)array[i]);\
257
lua_rawseti(L,-2,i+1);/* -1 is the number, -2 is the table*/ \
263
This is one giant macro to define the typemaps & the helpers
266
%define SWIG_TYPEMAP_NUM_ARR(NAME,TYPE)
267
%{SWIG_DECLARE_TYPEMAP_ARR_FN(NAME,TYPE);%}
269
// fixed size array's
270
%typemap(in) TYPE INPUT[ANY]
271
%{ $1 = SWIG_get_##NAME##_num_array_fixed(L,$input,$1_dim0);
272
if (!$1) SWIG_fail;%}
274
%typemap(freearg) TYPE INPUT[ANY]
275
%{ SWIG_FREE_ARRAY($1);%}
277
// variable size array's
278
%typemap(in) (TYPE *INPUT,int)
279
%{ $1 = SWIG_get_##NAME##_num_array_var(L,$input,&$2);
280
if (!$1) SWIG_fail;%}
282
%typemap(freearg) (TYPE *INPUT,int)
283
%{ SWIG_FREE_ARRAY($1);%}
286
%typemap(in,numargs=0) TYPE OUTPUT[ANY]
287
%{ $1 = SWIG_ALLOC_ARRAY(TYPE,$1_dim0); %}
289
%typemap(argout) TYPE OUTPUT[ANY]
290
%{ SWIG_write_##NAME##_num_array(L,$1,$1_dim0); SWIG_arg++; %}
292
%typemap(freearg) TYPE OUTPUT[ANY]
293
%{ SWIG_FREE_ARRAY($1); %}
295
// inout fixed arrays
296
%typemap(in) TYPE INOUT[ANY]=TYPE INPUT[ANY];
297
%typemap(argout) TYPE INOUT[ANY]=TYPE OUTPUT[ANY];
298
%typemap(freearg) TYPE INOUT[ANY]=TYPE INPUT[ANY];
299
// inout variable arrays
300
%typemap(in) (TYPE *INOUT,int)=(TYPE *INPUT,int);
301
%typemap(argout) (TYPE *INOUT,int)
302
%{ SWIG_write_##NAME##_num_array(L,$1,$2); SWIG_arg++; %}
303
%typemap(freearg) (TYPE *INOUT,int)=(TYPE *INPUT,int);
305
// TODO out variable arrays (is there a standard form for such things?)
308
// the following line of code
309
// declares the C helper fns for the array typemaps
310
// as well as defining typemaps for
311
// fixed len arrays in & out, & variable length arrays in
313
SWIG_TYPEMAP_NUM_ARR(int,int);
314
SWIG_TYPEMAP_NUM_ARR(uint,unsigned int);
315
SWIG_TYPEMAP_NUM_ARR(short,short);
316
SWIG_TYPEMAP_NUM_ARR(ushort,unsigned short);
317
SWIG_TYPEMAP_NUM_ARR(long,long);
318
SWIG_TYPEMAP_NUM_ARR(ulong,unsigned long);
319
SWIG_TYPEMAP_NUM_ARR(float,float);
320
SWIG_TYPEMAP_NUM_ARR(double,double);
322
// again enums are a problem so they need their own type
323
// we use the int conversion routine & recast it
324
%typemap(in) enum SWIGTYPE INPUT[ANY]
325
%{ $1 = ($ltype)SWIG_get_int_num_array_fixed(L,$input,$1_dim0);
326
if (!$1) SWIG_fail;%}
328
%typemap(freearg) enum SWIGTYPE INPUT[ANY]
329
%{ SWIG_FREE_ARRAY($1);%}
331
// variable size array's
332
%typemap(in) (enum SWIGTYPE *INPUT,int)
333
%{ $1 = ($ltype)SWIG_get_int_num_array_var(L,$input,&$2);
334
if (!$1) SWIG_fail;%}
336
%typemap(freearg) (enum SWIGTYPE *INPUT,int)
337
%{ SWIG_FREE_ARRAY($1);%}
340
%typemap(in,numargs=0) enum SWIGTYPE OUTPUT[ANY]
341
%{ $1 = SWIG_ALLOC_ARRAY(enum SWIGTYPE,$1_dim0); %}
343
%typemap(argout) enum SWIGTYPE OUTPUT[ANY]
344
%{ SWIG_write_int_num_array(L,(int*)$1,$1_dim0); SWIG_arg++; %}
346
%typemap(freearg) enum SWIGTYPE OUTPUT[ANY]
347
%{ SWIG_FREE_ARRAY($1); %}
349
// inout fixed arrays
350
%typemap(in) enum SWIGTYPE INOUT[ANY]=enum SWIGTYPE INPUT[ANY];
351
%typemap(argout) enum SWIGTYPE INOUT[ANY]=enum SWIGTYPE OUTPUT[ANY];
352
%typemap(freearg) enum SWIGTYPE INOUT[ANY]=enum SWIGTYPE INPUT[ANY];
353
// inout variable arrays
354
%typemap(in) (enum SWIGTYPE *INOUT,int)=(enum SWIGTYPE *INPUT,int);
355
%typemap(argout) (enum SWIGTYPE *INOUT,int)
356
%{ SWIG_write_int_num_array(L,(int*)$1,$2); SWIG_arg++; %}
357
%typemap(freearg) (enum SWIGTYPE *INOUT,int)=(enum SWIGTYPE *INPUT,int);
360
/* Surprisingly pointer arrays are easier:
361
this is because all ptr arrays become void**
362
so only a few fns are needed & a few casts
364
The function defined are
365
// created a fixed size array, reads the specified table
366
// and then fills the array with pointers (checking the type)
367
// returns ptr to the array if ok, or 0 for error
368
// (also pushes a error message to the stack)
369
void** SWIG_get_ptr_array_fixed(lua_State* L, int index, int size,swig_type_info *type);
370
// as per SWIG_get_ptr_array_fixed()
371
// but reads the entire table & creates an array of the correct size
372
// (if the table is empty, it returns an error rather than a zero length array)
373
void** SWIG_get_ptr_array_var(lua_State* L, int index, int* size,swig_type_info *type);
374
// writes a table to Lua with all the specified pointers
375
// all pointers have the ownership value 'own' (normally 0)
376
void SWIG_write_ptr_array(lua_State* L,void **array,int size,int own);
377
// read the specified table, and fills the array with ptrs
378
// returns 1 of ok (only fails if it doesnt find correct type of ptrs)
379
// helper fn (called by SWIG_get_ptr_array_*() fns)
380
int SWIG_read_ptr_array(lua_State* L,int index,void **array,int size,swig_type_info *type);
382
The key thing to remember is that it is assumed that there is no
383
modification of pointers ownership in the arrays
386
void pointers_in(TYPE* arr[],int len);
387
will make copies of the pointer into a temp array and then pass it into the fn
388
Lua does not remeber that this fn held the pointers, so it is not safe to keep
389
these pointers until later
392
void pointers_out(TYPE* arr[3]);
393
will return a table containing three pointers
394
however these pointers are NOT owned by Lua, merely borrowed
395
so if the C/C++ frees then Lua is not aware
400
int SWIG_read_ptr_array(lua_State* L,int index,void **array,int size,swig_type_info *type){
402
for (i = 0; i < size; i++) {
403
lua_rawgeti(L,index,i+1);
404
if (!lua_isuserdata(L,-1) || SWIG_ConvertPtr(L,-1,&array[i],type,0)==-1){
412
static void** SWIG_get_ptr_array_fixed(lua_State* L, int index, int size,swig_type_info *type){
414
if (!lua_istable(L,index) || SWIG_itable_size(L,index) != size) {
415
lua_pushfstring(L,"expected a table of size %d",size);
418
array=SWIG_ALLOC_ARRAY(void*,size);
419
if (!SWIG_read_ptr_array(L,index,array,size,type)){
420
lua_pushfstring(L,"table must contain pointers of type %s",type->name);
421
SWIG_FREE_ARRAY(array);
426
static void** SWIG_get_ptr_array_var(lua_State* L, int index, int* size,swig_type_info *type){
428
if (!lua_istable(L,index)) {
429
lua_pushstring(L,"expected a table");
432
*size=SWIG_itable_size(L,index);
434
lua_pushstring(L,"table appears to be empty");
437
array=SWIG_ALLOC_ARRAY(void*,*size);
438
if (!SWIG_read_ptr_array(L,index,array,*size,type)){
439
lua_pushfstring(L,"table must contain pointers of type %s",type->name);
440
SWIG_FREE_ARRAY(array);
445
void SWIG_write_ptr_array(lua_State* L,void **array,int size,swig_type_info *type,int own){
448
for (i = 0; i < size; i++){
449
SWIG_NewPointerObj(L,array[i],type,own);
450
lua_rawseti(L,-2,i+1);/* -1 is the number, -2 is the table*/
455
// fixed size array's
456
%typemap(in) SWIGTYPE* INPUT[ANY]
457
%{ $1 = ($ltype)SWIG_get_ptr_array_fixed(L,$input,$1_dim0,$*1_descriptor);
458
if (!$1) SWIG_fail;%}
460
%typemap(freearg) SWIGTYPE* INPUT[ANY]
461
%{ SWIG_FREE_ARRAY($1);%}
463
// variable size array's
464
%typemap(in) (SWIGTYPE **INPUT,int)
465
%{ $1 = ($ltype)SWIG_get_ptr_array_var(L,$input,&$2,$*1_descriptor);
466
if (!$1) SWIG_fail;%}
468
%typemap(freearg) (SWIGTYPE **INPUT,int)
469
%{ SWIG_FREE_ARRAY($1);%}
472
%typemap(in,numargs=0) SWIGTYPE* OUTPUT[ANY]
473
%{ $1 = SWIG_ALLOC_ARRAY($*1_type,$1_dim0); %}
475
%typemap(argout) SWIGTYPE* OUTPUT[ANY]
476
%{ SWIG_write_ptr_array(L,(void**)$1,$1_dim0,$*1_descriptor,0); SWIG_arg++; %}
478
%typemap(freearg) SWIGTYPE* OUTPUT[ANY]
479
%{ SWIG_FREE_ARRAY($1); %}
481
// inout fixed arrays
482
%typemap(in) SWIGTYPE* INOUT[ANY]=SWIGTYPE* INPUT[ANY];
483
%typemap(argout) SWIGTYPE* INOUT[ANY]=SWIGTYPE* OUTPUT[ANY];
484
%typemap(freearg) SWIGTYPE* INOUT[ANY]=SWIGTYPE* INPUT[ANY];
485
// inout variable arrays
486
%typemap(in) (SWIGTYPE** INOUT,int)=(SWIGTYPE** INPUT,int);
487
%typemap(argout) (SWIGTYPE** INOUT,int)
488
%{ SWIG_write_ptr_array(L,(void**)$1,$2,$*1_descriptor,0); SWIG_arg++; %}
489
%typemap(freearg) (SWIGTYPE**INOUT,int)=(SWIGTYPE**INPUT,int);