1 /* -----------------------------------------------------------------------------
2  * reference.i
3  *
4  * Accept Perl references as pointers
5  * ----------------------------------------------------------------------------- */
6 
7 /*
8 The following methods make Perl references work like simple C
9 pointers.  References can only be used for simple input/output
10 values, not C arrays however.  It should also be noted that
11 REFERENCES are specific to Perl and not supported in other
12 scripting languages at this time.
13 
14          int            *REFERENCE
15          short          *REFERENCE
16          long           *REFERENCE
17          unsigned int   *REFERENCE
18          unsigned short *REFERENCE
19          unsigned long  *REFERENCE
20          unsigned char  *REFERENCE
21          float          *REFERENCE
22          double         *REFERENCE
23 
24 For example, suppose you were trying to wrap the following function :
25 
26         void neg(double *x) {
27              *x = -(*x);
28         }
29 
30 You could wrap it with SWIG as follows :
31 
32         %include reference.i
33         void neg(double *REFERENCE);
34 
35 or you can use the %apply directive :
36 
37         %include reference.i
38         %apply double *REFERENCE { double *x };
39         void neg(double *x);
40 
41 Unlike the INOUT mapping described in typemaps.i, this approach directly
42 modifies the value of a Perl reference.  Thus, you could use it
43 as follows :
44 
45        $x = 3;
46        neg(\$x);
47        print "$x\n";         # Should print out -3.
48 
49 */
50 
51 %typemap(in) double *REFERENCE (double dvalue), double &REFERENCE(double dvalue)
52 {
53   SV *tempsv;
54   if (!SvROK($input)) {
55     SWIG_croak("expected a reference");
56   }
57   tempsv = SvRV($input);
58   if ((!SvNOK(tempsv)) && (!SvIOK(tempsv))) {
59 	printf("Received %d\n", SvTYPE(tempsv));
60 	SWIG_croak("Expected a double reference.");
61   }
62   dvalue = SvNV(tempsv);
63   $1 = &dvalue;
64 }
65 
66 %typemap(in) float *REFERENCE (float dvalue), float &REFERENCE(float dvalue)
67 {
68   SV *tempsv;
69   if (!SvROK($input)) {
70     SWIG_croak("expected a reference");
71   }
72   tempsv = SvRV($input);
73   if ((!SvNOK(tempsv)) && (!SvIOK(tempsv))) {
74     SWIG_croak("expected a double reference");
75   }
76   dvalue = (float) SvNV(tempsv);
77   $1 = &dvalue;
78 }
79 
80 %typemap(in) int *REFERENCE (int dvalue), int &REFERENCE (int dvalue)
81 {
82   SV *tempsv;
83   if (!SvROK($input)) {
84     SWIG_croak("expected a reference");
85   }
86   tempsv = SvRV($input);
87   if (!SvIOK(tempsv)) {
88     SWIG_croak("expected an integer reference");
89   }
90   dvalue = SvIV(tempsv);
91   $1 = &dvalue;
92 }
93 
94 %typemap(in) short *REFERENCE (short dvalue), short &REFERENCE(short dvalue)
95 {
96   SV *tempsv;
97   if (!SvROK($input)) {
98     SWIG_croak("expected a reference");
99   }
100   tempsv = SvRV($input);
101   if (!SvIOK(tempsv)) {
102     SWIG_croak("expected an integer reference");
103   }
104   dvalue = (short) SvIV(tempsv);
105   $1 = &dvalue;
106 }
107 %typemap(in) long *REFERENCE (long dvalue), long &REFERENCE(long dvalue)
108 {
109   SV *tempsv;
110   if (!SvROK($input)) {
111     SWIG_croak("expected a reference");
112   }
113   tempsv = SvRV($input);
114   if (!SvIOK(tempsv)) {
115     SWIG_croak("expected an integer reference");
116   }
117   dvalue = (long) SvIV(tempsv);
118   $1 = &dvalue;
119 }
120 %typemap(in) unsigned int *REFERENCE (unsigned int dvalue), unsigned int &REFERENCE(unsigned int dvalue)
121 {
122   SV *tempsv;
123   if (!SvROK($input)) {
124     SWIG_croak("expected a reference");
125   }
126   tempsv = SvRV($input);
127   if (!SvIOK(tempsv)) {
128     SWIG_croak("expected an integer reference");
129   }
130   dvalue = (unsigned int) SvUV(tempsv);
131   $1 = &dvalue;
132 }
133 %typemap(in) unsigned short *REFERENCE (unsigned short dvalue), unsigned short &REFERENCE(unsigned short dvalue)
134 {
135   SV *tempsv;
136   if (!SvROK($input)) {
137     SWIG_croak("expected a reference");
138   }
139   tempsv = SvRV($input);
140   if (!SvIOK(tempsv)) {
141     SWIG_croak("expected an integer reference");
142   }
143   dvalue = (unsigned short) SvUV(tempsv);
144   $1 = &dvalue;
145 }
146 %typemap(in) unsigned long *REFERENCE (unsigned long dvalue), unsigned long &REFERENCE(unsigned long dvalue)
147 {
148   SV *tempsv;
149   if (!SvROK($input)) {
150     SWIG_croak("expected a reference");
151   }
152   tempsv = SvRV($input);
153   if (!SvIOK(tempsv)) {
154     SWIG_croak("expected an integer reference");
155   }
156   dvalue = (unsigned long) SvUV(tempsv);
157   $1 = &dvalue;
158 }
159 
160 %typemap(in) unsigned char *REFERENCE (unsigned char dvalue), unsigned char &REFERENCE(unsigned char dvalue)
161 {
162   SV *tempsv;
163   if (!SvROK($input)) {
164     SWIG_croak("expected a reference");
165   }
166   tempsv = SvRV($input);
167   if (!SvIOK(tempsv)) {
168     SWIG_croak("expected an integer reference");
169   }
170   dvalue = (unsigned char) SvUV(tempsv);
171   $1 = &dvalue;
172 }
173 
174 %typemap(in) signed char *REFERENCE (signed char dvalue), signed char &REFERENCE(signed char dvalue)
175 {
176   SV *tempsv;
177   if (!SvROK($input)) {
178     SWIG_croak("expected a reference");
179   }
180   tempsv = SvRV($input);
181   if (!SvIOK(tempsv)) {
182     SWIG_croak("expected an integer reference");
183   }
184   dvalue = (signed char) SvIV(tempsv);
185   $1 = &dvalue;
186 }
187 
188 %typemap(in) bool *REFERENCE (bool dvalue), bool &REFERENCE(bool dvalue)
189 {
190   SV *tempsv;
191   if (!SvROK($input)) {
192     SWIG_croak("expected a reference");
193   }
194   tempsv = SvRV($input);
195   if (!SvIOK(tempsv)) {
196     SWIG_croak("expected an integer reference");
197   }
198   dvalue = SvIV(tempsv) ? true : false;
199   $1 = &dvalue;
200 }
201 
202 %typemap(typecheck) int *REFERENCE, int &REFERENCE,
203                     short *REFERENCE, short &REFERENCE,
204                     long *REFERENCE, long  &REFERENCE,
205                     signed char *REFERENCE, signed char &REFERENCE,
206                     bool *REFERENCE, bool &REFERENCE
207 {
208   $1 = SvROK($input) && SvIOK(SvRV($input));
209 }
210 %typemap(typecheck) double *REFERENCE, double &REFERENCE,
211                     float *REFERENCE, float &REFERENCE
212 {
213   $1 = SvROK($input);
214   if($1) {
215     SV *tmpsv = SvRV($input);
216     $1 = SvNOK(tmpsv) || SvIOK(tmpsv);
217   }
218 }
219 %typemap(typecheck) unsigned int   *REFERENCE, unsigned int &REFERENCE,
220                     unsigned short *REFERENCE, unsigned short &REFERENCE,
221                     unsigned long  *REFERENCE, unsigned long &REFERENCE,
222                     unsigned char  *REFERENCE, unsigned char &REFERENCE
223 {
224   $1 = SvROK($input);
225   if($1) {
226     SV *tmpsv = SvRV($input);
227     $1 = SvUOK(tmpsv) || SvIOK(tmpsv);
228   }
229 }
230 
231 %typemap(argout) double *REFERENCE, double &REFERENCE,
232                  float  *REFERENCE, float &REFERENCE
233 {
234   SV *tempsv;
235   tempsv = SvRV($arg);
236   if (!$1) SWIG_croak("expected a reference");
237   sv_setnv(tempsv, (double) *$1);
238 }
239 
240 %typemap(argout)       int            *REFERENCE, int &REFERENCE,
241                        short          *REFERENCE, short &REFERENCE,
242                        long           *REFERENCE, long  &REFERENCE,
243                        signed char    *REFERENCE, signed char &REFERENCE,
244                        bool           *REFERENCE, bool &REFERENCE
245 {
246   SV *tempsv;
247   tempsv = SvRV($input);
248   if (!$1) SWIG_croak("expected a reference");
249   sv_setiv(tempsv, (IV) *$1);
250 }
251 
252 %typemap(argout)       unsigned int   *REFERENCE, unsigned int &REFERENCE,
253                        unsigned short *REFERENCE, unsigned short &REFERENCE,
254                        unsigned long  *REFERENCE, unsigned long &REFERENCE,
255                        unsigned char  *REFERENCE, unsigned char &REFERENCE
256 {
257   SV *tempsv;
258   tempsv = SvRV($input);
259   if (!$1) SWIG_croak("expected a reference");
260   sv_setuv(tempsv, (UV) *$1);
261 }
262