1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 %typemap(in) (const char** in), (char** in)
21 {
22     AV *tempav;
23     I32 len;
24     int i;
25     SV  **tv;
26     if (!SvROK($input))
27         croak("Argument $argnum is not a reference.");
28         if (SvTYPE(SvRV($input)) != SVt_PVAV)
29         croak("Argument $argnum is not an array.");
30         tempav = (AV*)SvRV($input);
31     len = av_len(tempav) + 1;
32     if(len!=0)
33     {
34         $1 = (char **) safemalloc((len)*sizeof(char *));
35         for (i = 0; i < len; i++) {
36             tv = av_fetch(tempav, i, 0);
37             $1[i] = (char *) SvPV_nolen(*tv);
38         }
39     }
40     else
41     {
42        $1 = NULL;
43     }
44 }
45 %typemap(freearg) (const char** in), (char** in)  {
46     Safefree($1);
47 }
48 
49 %typemap(in) (const char **keys, const char **vals), (char **keys, char **vals), (const char* const* keys, const char* const* vals)
50 {
51     HV *temphv;
52     char *key;
53     SV *val;
54     I32 len;
55     int hash_len;
56     int i = 0;
57     if (!SvROK($input))
58         croak("Argument $argnum is not a reference.");
59         if (SvTYPE(SvRV($input)) != SVt_PVHV)
60     croak("Argument $argnum is not a hash.");
61         temphv = (HV*)SvRV($input);
62     hash_len = hv_iterinit(temphv);
63     if(hash_len)
64     {
65         $1 = (char **)safemalloc(hash_len*sizeof(char *));
66         $2 = (char **)safemalloc(hash_len*sizeof(char *));
67         while ((val = hv_iternextsv(temphv, &key, &len)))
68         {
69             $1[i] = key;
70             $2[i] = SvPV_nolen(val);
71             ++i;
72         }
73     }
74     else
75     {
76        $1 = NULL;
77        $2 = NULL;
78     }
79 }
80 %typemap(freearg) (const char **keys, const char **vals), (char **keys, char **vals)
81 {
82     Safefree($1);
83     Safefree($2);
84 }
85 
86 %typemap(in,numinputs=0) (const char **out) (char *temp)
87 {
88     temp = NULL;
89     $1 = &temp;
90 }
91 
92 %typemap(argout) (const char **out)
93 {
94     if(!result)
95     {
96         $result = newSVpv(*$1, 0);
97         sv_2mortal($result);
98         argvi++;
99     }
100 }
101 
102 %typemap(in) (void **out_pdata) (void *temp)
103 {
104     temp = NULL;
105     $1 = &temp;
106 }
107 
108 %typemap(argout) (void **out_pdata)
109 {
110     if(!result)
111     {
112         $result = newSVpvn((char*)(*$1), SvIV(ST(1)));
113         sv_2mortal($result);
114         argvi++;
115     }
116 }
117 
118 %typemap(in,numinputs=0) (int *out) (int temp), (bool *out) (bool temp), (uint64_t *out) (uint64_t temp), (int64_t *out) (int64_t temp)
119 {
120     temp = 0;
121     $1 = &temp;
122 }
123 
124 %typemap(argout) (int *out), (bool *out)
125 {
126     if(!result)
127     {
128         $result = newSViv(*$1);
129         sv_2mortal($result);
130         argvi++;
131     }
132 }
133 
134 %typemap(argout) (uint64_t *out), (int64_t *out)
135 {
136     if(!result)
137     {
138         $result = newSVnv((double)(*$1));
139         sv_2mortal($result);
140         argvi++;
141     }
142 }
143 
144 
145 %typemap(in,numinputs=0) (const int **out_stypes) (int* temp)
146 {
147     temp = NULL;
148     $1 = &temp;
149 }
150 
151 %typemap(argout) (const int **out_stypes)
152 {
153     if(av_len((AV*)SvRV(ST(3))) == -1 && !result)
154     {
155         AV *myav;
156         SV **svs;
157         int i = 0;
158         svs = (SV **)safemalloc(*arg4*sizeof(SV *));
159         for (i = 0; i < *arg4 ; i++) {
160             svs[i] = newSViv((*$1)[i]);
161             sv_2mortal(svs[i]);
162         }
163         myav = av_make(*arg4, svs);
164         Safefree(svs);
165         $result = newRV_noinc((SV*)myav);
166         sv_2mortal($result);
167         argvi++;
168     }
169 }
170 
171 %typemap(in,numinputs=0) (nn_uint *out_size, const char ***out_array) (nn_uint temp_size, char** temp),
172                          (mx_uint *out_size, const char ***out_array) (mx_uint temp_size, char** temp),
173                          (uint32_t *out_size, const char ***out_array) (uint32_t temp_size, char** temp)
174 {
175     $1 = &temp_size;
176     *$1 = 0;
177     $2 = &temp;
178 }
179 
180 %typemap(argout) (nn_uint *out_size, const char ***out_array),
181                  (mx_uint *out_size, const char ***out_array),
182                  (uint32_t *out_size, const char ***out_array)
183 {
184     if(!result)
185     {
186         AV *myav;
187         SV **svs;
188         int i = 0;
189         svs = (SV **)safemalloc(*$1*sizeof(SV *));
190         for (i = 0; i < *$1 ; i++) {
191             svs[i] = newSVpv((*$2)[i],0);
192             sv_2mortal(svs[i]);
193         }
194         myav = av_make(*$1,svs);
195         Safefree(svs);
196         $result = newRV_noinc((SV*)myav);
197         sv_2mortal($result);
198         argvi++;
199     }
200 }
201 
202 %typemap(in,numinputs=0) (const LibFeature **libFeature, size_t *size) (LibFeature *temp1, size_t temp2)
203 {
204     $1 = &temp1;
205     $2 = &temp2;
206     *$2 = 0;
207 }
208 
209 %typemap(argout) (const LibFeature **libFeature, size_t *size)
210 {
211     if(!result)
212     {
213         HV* hash = newHV();
214         for(int i = 0; i < *$2; i++)
215         {
216             hv_store(hash, ((*$1)[i]).name, strlen(((*$1)[i]).name), newSViv(((*$1)[i]).enabled), 0);
217         }
218         $result = newRV_noinc((SV*)hash);
219         sv_2mortal($result);
220         argvi++;
221     }
222 }
223 
224 %typemap(in,numinputs=0) (mx_uint *out_size, const char ***out_array2) (mx_uint temp_size, char** temp),
225                          (uint32_t *out_size, const char ***out_array2) (uint32_t temp_size, char** temp)
226 {
227     $1 = &temp_size;
228     *$1 = 0;
229     $2 = &temp;
230 }
231 
232 %typemap(argout) (mx_uint *out_size, const char ***out_array2),
233                  (uint32_t *out_size, const char ***out_array2)
234 {
235     if(!result)
236     {
237         AV *myav;
238         SV **svs;
239         int i = 0;
240         svs = (SV **)safemalloc(*$1*sizeof(SV *)*2);
241         for (i = 0; i < *$1*2 ; i++) {
242             svs[i] = newSVpv((*$2)[i],0);
243             sv_2mortal(svs[i]);
244         }
245         myav = av_make(*$1*2,svs);
246         Safefree(svs);
247         $result = newRV_noinc((SV*)myav);
248         sv_2mortal($result);
249         argvi++;
250     }
251 }
252 
253 %typemap(in) (uint32_t in), (const uint32_t in), (mx_uint in), (const mx_uint in)
254 {
255     $1 = (uint32_t)SvIV($input);
256 }
257 
258 %typemap(in) (uint64_t in), (const uint64_t in)
259 {
260     $1 = (uint64_t)SvUV($input);
261 }
262 
263 %typemap(in) (int64_t in), (const int64_t in)
264 {
265     $1 = (int64_t)SvUV($input);
266 }
267 
268 %typemap(in) (FunctionHandle in)
269 {
270     int res;
271     void **void_ptrptr = const_cast< void** >(&$1);
272     res = SWIG_ConvertPtr($input,void_ptrptr, 0, 0);
273     if (!SWIG_IsOK(res)) {
274         SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "FunctionHandle""'");
275     }
276 }
277 
278 %typemap(in) (AtomicSymbolCreator in)
279 {
280     int res = SWIG_ConvertPtr($input,&$1, 0, 0);
281     if (!SWIG_IsOK(res)) {
282         SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "AtomicSymbolCreator""'");
283     }
284 }
285 
286 %typemap(in) (const void *in), (void *in)
287 {
288     $1 = (void *)SvPV_nolen($input);
289 }
290 
291 %typemap(in) (const char *in)
292 {
293     $1 = SvPV_nolen($input);
294 }
295 
296 %typemap(in) (const mx_uint *in), (mx_uint *in), (const uint32_t *in), (uint32_t *in)
297 {
298     AV *tempav;
299     int i;
300     SV  **tv;
301     int av_len;
302     if (!SvROK($input))
303         croak("Argument $argnum is not a reference.");
304         if (SvTYPE(SvRV($input)) != SVt_PVAV)
305         croak("Argument $argnum is not an array.");
306         tempav = (AV*)SvRV($input);
307     av_len = av_len(tempav) + 1;
308     if(av_len)
309     {
310         $1 = (mx_uint *)safemalloc(av_len*sizeof(mx_uint));
311         for (i = 0; i < av_len; i++) {
312             tv = av_fetch(tempav, i, 0);
313             $1[i] = (mx_uint)SvIV(*tv);
314         }
315     }
316     else
317     {
318        $1 = NULL;
319     }
320 }
321 
322 %typemap(in) (const uint64_t *in), (uint64_t *in)
323 {
324     AV *tempav;
325     int i;
326     SV  **tv;
327     int av_len;
328     if (!SvROK($input))
329         croak("Argument $argnum is not a reference.");
330         if (SvTYPE(SvRV($input)) != SVt_PVAV)
331         croak("Argument $argnum is not an array.");
332         tempav = (AV*)SvRV($input);
333     av_len = av_len(tempav) + 1;
334     if(av_len)
335     {
336         $1 = (uint64_t *)safemalloc(av_len*sizeof(uint64_t));
337         for (i = 0; i < av_len; i++) {
338             tv = av_fetch(tempav, i, 0);
339             $1[i] = (uint64_t)SvUV(*tv);
340         }
341     }
342     else
343     {
344        $1 = NULL;
345     }
346 }
347 
348 %typemap(in) (const int64_t *in), (int64_t *in)
349 {
350     AV *tempav;
351     int i;
352     SV  **tv;
353     int av_len;
354     if (!SvROK($input))
355         croak("Argument $argnum is not a reference.");
356         if (SvTYPE(SvRV($input)) != SVt_PVAV)
357         croak("Argument $argnum is not an array.");
358         tempav = (AV*)SvRV($input);
359     av_len = av_len(tempav) + 1;
360     if(av_len)
361     {
362         $1 = (int64_t *)safemalloc(av_len*sizeof(int64_t));
363         for (i = 0; i < av_len; i++) {
364             tv = av_fetch(tempav, i, 0);
365             $1[i] = (int64_t)SvUV(*tv);
366         }
367     }
368     else
369     {
370        $1 = NULL;
371     }
372 }
373 
374 %typemap(freearg) (const mx_uint *in), (mx_uint *in), (const uint32_t *in),
375                   (uint32_t *in), (const uint64_t *in), (uint64_t *in), (const int64_t *in), (int64_t *in)
376 {
377     Safefree($1);
378 }
379 
380 %typemap(in) (const int *in), (int *in)
381 {
382     AV *tempav;
383     int i;
384     SV  **tv;
385     int av_len;
386     if (!SvROK($input))
387         croak("Argument $argnum is not a reference.");
388         if (SvTYPE(SvRV($input)) != SVt_PVAV)
389         croak("Argument $argnum is not an array.");
390         tempav = (AV*)SvRV($input);
391     av_len = av_len(tempav) + 1;
392     if(av_len)
393     {
394         $1 = (int *)safemalloc(av_len*sizeof(int));
395         for (i = 0; i < av_len; i++) {
396             tv = av_fetch(tempav, i, 0);
397             $1[i] = (int)SvIV(*tv);
398         }
399     }
400     else
401     {
402        $1 = NULL;
403     }
404 
405 }
406 
407 %typemap(freearg) (const int *in), (int *in) {
408     Safefree($1);
409 }
410 
411 %typemap(in) (dim_t *in)
412 {
413     AV *tempav;
414     int i;
415     SV  **tv;
416     int av_len;
417     if (!SvROK($input))
418         croak("Argument $argnum is not a reference.");
419         if (SvTYPE(SvRV($input)) != SVt_PVAV)
420         croak("Argument $argnum is not an array.");
421         tempav = (AV*)SvRV($input);
422     av_len = av_len(tempav) + 1;
423     if(av_len)
424     {
425         $1 = (dim_t *)safemalloc(av_len*sizeof(dim_t));
426         for (i = 0; i < av_len; i++) {
427             tv = av_fetch(tempav, i, 0);
428             $1[i] = (dim_t)SvIV(*tv);
429         }
430     }
431     else
432     {
433        $1 = NULL;
434     }
435 }
436 
437 %typemap(freearg) (dim_t *in) {
438     Safefree($1);
439 }
440 
441 %typemap(in) (NDArrayHandle* in), (SymbolHandle* in)
442 {
443     AV *tempav;
444     int i;
445     SV  **tv;
446     int res;
447     int av_len;
448     if (!SvROK($input))
449         croak("Argument $argnum is not a reference.");
450         if (SvTYPE(SvRV($input)) != SVt_PVAV)
451         croak("Argument $argnum is not an array.");
452         tempav = (AV*)SvRV($input);
453     av_len = av_len(tempav) + 1;
454     if(av_len)
455     {
456         $1 = ($1_type)safemalloc(av_len*sizeof($*1_type));
457         for (i = 0; i < av_len; i++) {
458             tv = av_fetch(tempav, i, 0);
459             res = SWIG_ConvertPtr(*tv,SWIG_as_voidptrptr(&$1[i]), $*1_descriptor, 0);
460             if (!SWIG_IsOK(res)) {
461                 SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "$*1_type""'");
462             }
463         }
464     }
465     else
466     {
467        $1 = NULL;
468     }
469 }
470 %typemap(freearg) (NDArrayHandle* in), (SymbolHandle* in) {
471     Safefree($1);
472 }
473 
474 %typemap(in) (void** cuda_kernel_args)
475 {
476     AV *tempav;
477     int i;
478     SV  **tv;
479     int res;
480     int av_len;
481     if (!SvROK($input))
482         croak("Argument $argnum is not a reference.");
483         if (SvTYPE(SvRV($input)) != SVt_PVAV)
484         croak("Argument $argnum is not an array.");
485         tempav = (AV*)SvRV($input);
486     av_len = av_len(tempav) + 1;
487     if(av_len)
488     {
489         $1 = ($1_type)safemalloc(av_len*sizeof($*1_type));
490         for (i = 0; i < av_len; i++) {
491             tv = av_fetch(tempav, i, 0);
492             res = SWIG_ConvertPtr(*tv,SWIG_as_voidptrptr(&$1[i]), SWIGTYPE_p_MXNDArray, 0);
493             if (!SWIG_IsOK(res)) {
494                 $1[i] = (void*)SvPV_nolen(*tv);
495             }
496         }
497     }
498     else
499     {
500        $1 = NULL;
501     }
502 }
503 %typemap(freearg) (void** cuda_kernel_args) {
504     Safefree($1);
505 }
506 
507 %typemap(in) (mx_float *in), (float *in)
508 {
509     AV *tempav;
510     int i, len;
511     SV  **tv;
512     if (!SvROK($input))
513         croak("Argument $argnum is not a reference.");
514         if (SvTYPE(SvRV($input)) != SVt_PVAV)
515         croak("Argument $argnum is not an array.");
516         tempav = (AV*)SvRV($input);
517     len = av_len(tempav) + 1;
518     if(len)
519     {
520         $1 = (mx_float *)safemalloc(len*sizeof(mx_float));
521         for (i = 0; i < len; i++) {
522             tv = av_fetch(tempav, i, 0);
523             $1[i] = (mx_float)SvNV(*tv);
524         }
525     }
526     else
527     {
528        $1 = NULL;
529     }
530 }
531 
532 %typemap(freearg) (mx_float *in), (float *in) {
533     Safefree($1);
534 }
535 
536 %typemap(in,numinputs=0) (NDArrayHandle *out) (NDArrayHandle temp),
537                          (FunctionHandle* out) (FunctionHandle temp),
538                          (SymbolHandle *out) (SymbolHandle temp),
539                          (ExecutorHandle *out) (ExecutorHandle temp),
540                          (DataIterHandle *out) (ExecutorHandle temp),
541                          (KVStoreHandle *out) (KVStoreHandle temp),
542                          (RecordIOHandle *out) (RecordIOHandle temp),
543                          (RtcHandle *out) (RtcHandle temp),
544                          (CachedOpHandle *out) (CachedOpHandle temp),
545                          (CudaModuleHandle *out) (CudaModuleHandle temp),
546                          (CudaKernelHandle *out) (CudaKernelHandle temp)
547 {
548     $1 = &temp;
549 }
550 %typemap(argout) (NDArrayHandle *out), (FunctionHandle* out), (SymbolHandle *out), (ExecutorHandle *out), (DataIterHandle *out),
551                  (KVStoreHandle *out), (RecordIOHandle *out), (RtcHandle *out) (RtcHandle temp), (CachedOpHandle *out) (CachedOpHandle temp),
552                  (CudaModuleHandle *out) (CudaModuleHandle temp), (CudaKernelHandle *out) (CudaKernelHandle temp)
553 
554 {
555     if(!result)
556     {
557         $result =  SWIG_NewPointerObj(SWIG_as_voidptr(*$1), $*1_descriptor, 0); argvi++;
558     }
559 }
560 
561 %typemap(in) (mx_float **out_pdata) (mx_float *temp_pdata), (float **out_pdata) (float *temp_pdata)
562 {
563     $1 = &temp_pdata;
564 }
565 %typemap(argout) (mx_float **out_pdata)
566 {
567     if(!result)
568     {
569         AV *myav;
570         SV **svs;
571         int len;
572         int i = 0;
573         len = SvIV($input);
574         svs = (SV **)safemalloc(len*sizeof(SV *));
575         for (i = 0; i < len ; i++) {
576             svs[i] = newSVnv((*$1)[i]);
577             sv_2mortal(svs[i]);
578         }
579         myav = av_make(len,svs);
580         Safefree(svs);
581         $result = newRV_noinc((SV*)myav);
582         sv_2mortal($result);
583         argvi++;
584     }
585 }
586 
587 %typemap(in,numinputs=0) (char const **out_array, size_t *out_size) (char * temp, size_t temp_size)
588 {
589     $2 = &temp_size;
590     *$2 = 0;
591     $1 = &temp;
592 }
593 
594 %typemap(argout) (char const **out_array, size_t *out_size)
595 {
596     if(!result)
597     {
598         $result = newSVpvn(*$1, *$2);
599         sv_2mortal($result);
600         argvi++;
601     }
602 }
603 
604 %typemap(in,numinputs=0) (size_t *out_size, char const **out_array) (size_t temp_size, char *temp)
605 {
606     $1 = &temp_size;
607     *$1 = 0;
608     $2 = &temp;
609 }
610 
611 %typemap(argout) (size_t *out_size, char const **out_array)
612 {
613     if(!result)
614     {
615         $result = newSVpvn(*$2, *$1);
616         sv_2mortal($result);
617         argvi++;
618     }
619 }
620 
621 %typemap(in,numinputs=0) (int *out_dim, const int **out_pdata) (int temp_dim, int *temp_pdata),
622                          (int *out_dim, const int64_t **out_pdata) (int temp_dim, int64_t *temp_pdata)
623 {
624     $1 = &temp_dim;
625     $2 = &temp_pdata;
626 }
627 
628 %typemap(argout) (int *out_dim, const int64_t **out_pdata)
629 {
630     if(!result)
631     {
632         AV *myav;
633         SV **svs;
634         int i = 0;
635         svs = (SV **)safemalloc(*$1*sizeof(SV *));
636         for (i = 0; i < *$1 ; i++) {
637             svs[i] = newSVnv((double)((*$2)[i]));
638             sv_2mortal(svs[i]);
639         }
640         myav = av_make(*$1,svs);
641         Safefree(svs);
642         $result = newRV_noinc((SV*)myav);
643         sv_2mortal($result);
644         argvi++;
645     }
646 }
647 
648 %typemap(argout) (int *out_dim, const int **out_pdata)
649 {
650     if(!result)
651     {
652         AV *myav;
653         SV **svs;
654         int i = 0;
655         svs = (SV **)safemalloc(*$1*sizeof(SV *));
656         for (i = 0; i < *$1 ; i++) {
657             svs[i] = newSViv((*$2)[i]);
658             sv_2mortal(svs[i]);
659         }
660         myav = av_make(*$1,svs);
661         Safefree(svs);
662         $result = newRV_noinc((SV*)myav);
663         sv_2mortal($result);
664         argvi++;
665     }
666 }
667 
668 %typemap(in,numinputs=0) (uint64_t **out_index, uint64_t *out_size) (uint64_t *temp1, uint64_t temp2)
669 {
670     $1 = &temp1;
671     $2 = &temp2;
672     *$2 = 0;
673 }
674 
675 %typemap(argout) (uint64_t **out_index, uint64_t *out_size)
676 {
677     if(!result)
678     {
679         AV *myav;
680         SV **svs;
681         uint64_t i = 0;
682         svs = (SV **)safemalloc(*$2*sizeof(SV *));
683         for (i = 0; i < *$2 ; i++) {
684             svs[i] = newSVnv((double)((*$1)[i]));
685             sv_2mortal(svs[i]);
686         }
687         myav = av_make(*$2,svs);
688         Safefree(svs);
689         $result = newRV_noinc((SV*)myav);
690         sv_2mortal($result);
691         argvi++;
692     }
693 }
694 
695 %typemap(in,numinputs=0) (mx_uint *out_size, FunctionHandle** out_array) (mx_uint temp_size, FunctionHandle* temp),
696                          (mx_uint *out_size, AtomicSymbolCreator** out_array) (mx_uint temp_size, AtomicSymbolCreator* temp),
697                          (mx_uint *out_size, DataIterCreator **out_array) (mx_uint temp_size, DataIterCreator* temp),
698                          (mx_uint *out_size, NDArrayHandle** out_array) (mx_uint temp_size, NDArrayHandle* temp),
699                          (uint32_t *out_size, FunctionHandle** out_array) (uint32_t temp_size, FunctionHandle* temp),
700                          (uint32_t *out_size, AtomicSymbolCreator** out_array) (uint32_t temp_size, AtomicSymbolCreator* temp),
701                          (uint32_t *out_size, DataIterCreator **out_array) (uint32_t temp_size, DataIterCreator* temp),
702                          (uint32_t *out_size, NDArrayHandle** out_array) (uint32_t temp_size, NDArrayHandle* temp)
703 
704 {
705     $1 = &temp_size;
706     *$1 = 0;
707     $2 = &temp;
708 }
709 
710 // many argouts needed because SWIG can't $**2_mangle
711 %typemap(argout) (mx_uint *out_size, AtomicSymbolCreator** out_array),
712                  (uint32_t *out_size, AtomicSymbolCreator** out_array)
713 {
714     if(!result)
715     {
716         AV *myav;
717         SV **svs;
718         int i = 0;
719         svs = (SV **)safemalloc(*$1*sizeof(SV *));
720         for (i = 0; i < *$1 ; i++) {
721             svs[i] = SWIG_NewPointerObj(SWIG_as_voidptr((*$2)[i]), SWIGTYPE_p_MXAtomicSymbolCreator, 0);
722         }
723         myav = av_make(*$1,svs);
724         Safefree(svs);
725         $result = newRV_noinc((SV*)myav);
726         sv_2mortal($result);
727         argvi++;
728     }
729 }
730 
731 %typemap(argout) (mx_uint *out_size, FunctionHandle** out_array),
732                  (uint32_t *out_size, FunctionHandle** out_array)
733 {
734     if(!result)
735     {
736         AV *myav;
737         SV **svs;
738         int i = 0;
739         svs = (SV **)safemalloc(*$1*sizeof(SV *));
740         for (i = 0; i < *$1 ; i++) {
741             svs[i] = SWIG_NewPointerObj(SWIG_as_voidptr((*$2)[i]), SWIGTYPE_p_MXFunction, 0);
742         }
743         myav = av_make(*$1,svs);
744         Safefree(svs);
745         $result = newRV_noinc((SV*)myav);
746         sv_2mortal($result);
747         argvi++;
748     }
749 }
750 
751 %typemap(argout) (mx_uint *out_size, DataIterCreator **out_array),
752                  (uint32_t *out_size, DataIterCreator **out_array)
753 {
754     if(!result)
755     {
756         AV *myav;
757         SV **svs;
758         int i = 0;
759         svs = (SV **)safemalloc(*$1*sizeof(SV *));
760         for (i = 0; i < *$1 ; i++) {
761             svs[i] = SWIG_NewPointerObj(SWIG_as_voidptr((*$2)[i]), SWIGTYPE_p_MXDataIterCreator, 0);
762         }
763         myav = av_make(*$1,svs);
764         Safefree(svs);
765         $result = newRV_noinc((SV*)myav);
766         sv_2mortal($result);
767         argvi++;
768     }
769 }
770 
771 %typemap(argout) (mx_uint *out_size, NDArrayHandle** out_array),
772                  (uint32_t *out_size, NDArrayHandle** out_array)
773 {
774     if(!result)
775     {
776         AV *myav;
777         SV **svs;
778         int i = 0;
779         svs = (SV **)safemalloc(*$1*sizeof(SV *));
780         for (i = 0; i < *$1 ; i++) {
781             svs[i] = SWIG_NewPointerObj(SWIG_as_voidptr((*$2)[i]), SWIGTYPE_p_MXNDArray, 0);
782         }
783         myav = av_make(*$1,svs);
784         Safefree(svs);
785         $result = newRV_noinc((SV*)myav);
786         sv_2mortal($result);
787         argvi++;
788     }
789 }
790 
791 %typemap(in,numinputs=0) (mx_uint* couple_out_size, NDArrayHandle** out_first_array, NDArrayHandle** out_second_array)
792                          (mx_uint t, NDArrayHandle* t1, NDArrayHandle* t2),
793                          (uint32_t* couple_out_size, NDArrayHandle** out_first_array, NDArrayHandle** out_second_array)
794                          (uint32_t t, NDArrayHandle* t1, NDArrayHandle* t2)
795 {
796     $1 = &t;
797     *$1 = 0;
798     $2 = &t1;
799     $3 = &t2;
800 }
801 
802 %typemap(argout) (mx_uint* couple_out_size, NDArrayHandle** out_first_array, NDArrayHandle** out_second_array),
803                  (uint32_t* couple_out_size, NDArrayHandle** out_first_array, NDArrayHandle** out_second_array)
804 {
805     if(!result)
806     {
807         AV *container, *in_args, *arg_grads;
808         int i;
809         container = newAV();
810         in_args = newAV();
811         arg_grads = newAV();
812         for (i = 0; i < *$1 ; i++) {
813             av_push(in_args, SvREFCNT_inc(SWIG_NewPointerObj(SWIG_as_voidptr((*$2)[i]), SWIGTYPE_p_MXNDArray, 0)));
814             av_push(arg_grads, SvREFCNT_inc(SWIG_NewPointerObj(SWIG_as_voidptr((*$3)[i]), SWIGTYPE_p_MXNDArray, 0)));
815         }
816         av_push(container, newRV_noinc((SV*)in_args));
817         av_push(container, newRV_noinc((SV*)arg_grads));
818         $result = newRV_noinc((SV*)container);
819         sv_2mortal($result);
820         argvi++;
821     }
822 }
823 
824 %typemap(in,numinputs=0) (NDArrayHandle **out_grad) (NDArrayHandle* temp)
825 {
826     int vars = SvIV(ST(3));
827     if(vars)
828     {
829         $1 = &temp;
830     }
831     else
832     {
833         $1 = NULL;
834     }
835 }
836 
837 
838 %typemap(argout) (NDArrayHandle** out_grad)
839 {
840     if(!result)
841     {
842         AV *myav;
843         SV **svs;
844         int i = 0;
845         int len = SvIV(ST(3));
846         svs = (SV **)safemalloc(len*sizeof(SV *));
847         for (i = 0; i < len ; i++) {
848             svs[i] = SWIG_NewPointerObj(SWIG_as_voidptr((*$1)[i]), SWIGTYPE_p_MXNDArray, 0);
849         }
850         myav = av_make(len,svs);
851         Safefree(svs);
852         $result = newRV_noinc((SV*)myav);
853         sv_2mortal($result);
854         argvi++;
855     }
856 }
857 
858 %typemap(in,numinputs=0) (int **out_stype) (int *temp)
859 {
860     int vars = SvIV(ST(3));
861     if(vars)
862     {
863         $1 = &temp;
864     }
865     else
866     {
867         $1 = NULL;
868     }
869 }
870 
871 %typemap(argout) (int** out_stype)
872 {
873     if(!result)
874     {
875         AV *myav;
876         SV **svs;
877         int i = 0;
878         int len = SvIV(ST(3));
879         svs = (SV **)safemalloc(len*sizeof(SV *));
880         for (i = 0; i < len ; i++) {
881             svs[i] = newSViv((*$1)[i]);
882         }
883         myav = av_make(len,svs);
884         Safefree(svs);
885         $result = newRV_noinc((SV*)myav);
886         sv_2mortal($result);
887         argvi++;
888     }
889 }
890 
891 %typemap(in) (int *out_size, NDArrayHandle** out_array) (int temp, NDArrayHandle* temp_array)
892 {
893     AV *tempav;
894     int i;
895     SV  **tv;
896     int res;
897     int av_len;
898     if (!SvROK($input))
899         croak("Argument $argnum is not a reference.");
900         if (SvTYPE(SvRV($input)) != SVt_PVAV)
901         croak("Argument $argnum is not an array.");
902         tempav = (AV*)SvRV($input);
903     av_len = av_len(tempav) + 1;
904     temp_array = NULL;
905     if(av_len)
906     {
907         temp_array = (void**)safemalloc(av_len*sizeof(void*));
908         for (i = 0; i < av_len; i++) {
909             tv = av_fetch(tempav, i, 0);
910             res = SWIG_ConvertPtr(*tv,SWIG_as_voidptrptr(&(temp_array[i])), 0, 0);
911             if (!SWIG_IsOK(res)) {
912                 SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "NDArray""'");
913             }
914         }
915     }
916     temp = av_len;
917     $1 = &temp;
918     $2 = &temp_array;
919 }
920 
921 %typemap(freearg) (int *out_size, NDArrayHandle** out_array) {
922     if(av_len((AV*)SvRV(ST(3))) > -1)
923     {
924         Safefree(*$2);
925     }
926 }
927 
928 %typemap(argout) (int *out_size, NDArrayHandle** out_array)
929 {
930     SV **svs;
931     int i = 0;
932     if(av_len((AV*)SvRV(ST(3))) == -1)
933     {
934         if(!result)
935         {
936             AV *container = newAV();
937             for (i = 0; i < *$1 ; i++) {
938                 av_push(container, SvREFCNT_inc(SWIG_NewPointerObj(SWIG_as_voidptr((*$2)[i]), SWIGTYPE_p_MXNDArray, 0)));
939             }
940             $result = newRV_noinc((SV*)container);
941             sv_2mortal($result);
942             argvi++;
943         }
944     }
945 }
946 
947 %typemap(in,numinputs=0) (const char **name,
948                           const char **description,
949                           uint32_t *num_args,
950                           const char ***arg_names,
951                           const char ***arg_type_infos,
952                           const char ***arg_descriptions
953                           )
954                           (char *name_temp,
955                            char *desc_temp,
956                            uint32_t num_args_temp,
957                            char **names_temp,
958                            char **types_temp,
959                            char **descs_temp
960                            )
961 {
962     $1 = &name_temp;
963     $2 = &desc_temp;
964     $3 = &num_args_temp;
965     *$3 = 0;
966     $4 = &names_temp;
967     $5 = &types_temp;
968     $6 = &descs_temp;
969 }
970 
971 %typemap(argout) (const char **name,
972                   const char **description,
973                   uint32_t *num_args,
974                   const char ***arg_names,
975                   const char ***arg_type_infos,
976                   const char ***arg_descriptions
977                   )
978 {
979     if(!result)
980     {
981         AV *container, *names, *types, *descs;
982         int i;
983         container = newAV();
984         names = newAV();
985         types = newAV();
986         descs = newAV();
987         if($1) av_push(container, newSVpv(*$1,0));
988         if($2) av_push(container, newSVpv(*$2,0));
989         if($3)
990         {
991             for (i = 0; i < *$3 ; i++) {
992                 av_push(names, newSVpv((*$4)[i],0));
993                 av_push(types, newSVpv((*$5)[i],0));
994                 av_push(descs, newSVpv((*$6)[i],0));
995             }
996         }
997         av_push(container, newRV_noinc((SV*)names));
998         av_push(container, newRV_noinc((SV*)types));
999         av_push(container, newRV_noinc((SV*)descs));
1000         $result = newRV_noinc((SV*)container);
1001         sv_2mortal($result);
1002         argvi++;
1003     }
1004 }
1005 
1006 %typemap(in,numinputs=0) (const char **name,
1007                           const char **description,
1008                           uint32_t *num_args,
1009                           const char ***arg_names,
1010                           const char ***arg_type_infos,
1011                           const char ***arg_descriptions,
1012                           const char **key_var_num_args
1013                           )
1014                           (char *name_temp,
1015                            char *desc_temp,
1016                            uint32_t num_args_temp,
1017                            char **names_temp,
1018                            char **types_temp,
1019                            char **descs_temp,
1020                            char *key_temp
1021                            )
1022 {
1023     $1 = &name_temp;
1024     $2 = &desc_temp;
1025     $3 = &num_args_temp;
1026     *$3 = 0;
1027     $4 = &names_temp;
1028     $5 = &types_temp;
1029     $6 = &descs_temp;
1030     $7 = &key_temp;
1031 }
1032 
1033 %typemap(argout) (const char **name,
1034                   const char **description,
1035                   uint32_t *num_args,
1036                   const char ***arg_names,
1037                   const char ***arg_type_infos,
1038                   const char ***arg_descriptions,
1039                   const char **key_var_num_args
1040                   )
1041 {
1042     if(!result)
1043     {
1044         AV *container, *names, *types, *descs;
1045         int i;
1046         container = newAV();
1047         names = newAV();
1048         types = newAV();
1049         descs = newAV();
1050         if($1) av_push(container, newSVpv(*$1,0));
1051         if($2) av_push(container, newSVpv(*$2,0));
1052         if($3)
1053         {
1054             for (i = 0; i < *$3 ; i++) {
1055                 av_push(names, newSVpv((*$4)[i],0));
1056                 av_push(types, newSVpv((*$5)[i],0));
1057                 av_push(descs, newSVpv((*$6)[i],0));
1058             }
1059         }
1060         av_push(container, newRV_noinc((SV*)names));
1061         av_push(container, newRV_noinc((SV*)types));
1062         av_push(container, newRV_noinc((SV*)descs));
1063         if($7) av_push(container, newSVpv(*$7,0));
1064         $result = newRV_noinc((SV*)container);
1065         sv_2mortal($result);
1066         argvi++;
1067     }
1068 }
1069 
1070 %typemap(in,numinputs=0) (uint32_t *out) (uint32_t temp), (size_t *out) (size_t temp)
1071 {
1072     $1 = &temp;
1073     *$1 = 0;
1074 }
1075 
1076 %typemap(argout) (uint32_t *out), (size_t *out)
1077 {
1078     if(!result)
1079     {
1080         $result = newSViv(*$1);
1081         sv_2mortal($result);
1082         argvi++;
1083     }
1084 }
1085 
1086 %typemap(in,numinputs=0) (uint32_t *in_shape_size, const int **in_shape_ndim, const int ***in_shape_data)
1087                          (uint32_t temp1, int *temp2, int **temp3),
1088                          (uint32_t *out_shape_size, const int **out_shape_ndim, const int ***out_shape_data)
1089                          (uint32_t temp1, int *temp2, int **temp3),
1090                          (uint32_t *aux_shape_size, const int **aux_shape_ndim, const int ***aux_shape_data)
1091                          (uint32_t temp1, int *temp2, int **temp3),
1092                          (size_t *in_shape_size, const int **in_shape_ndim, const int64_t ***in_shape_data)
1093                          (size_t temp1, int *temp2, int64_t **temp3),
1094                          (size_t *out_shape_size, const int **out_shape_ndim, const int64_t ***out_shape_data)
1095                          (size_t temp1, int *temp2, int64_t **temp3),
1096                          (size_t *aux_shape_size, const int **aux_shape_ndim, const int64_t ***aux_shape_data)
1097                          (size_t temp1, int *temp2, int64_t **temp3)
1098 {
1099     $1 = &temp1;
1100     $2 = &temp2;
1101     $3 = &temp3;
1102     *$1 = 0;
1103 }
1104 
1105 %typemap(argout) (uint32_t *in_shape_size, const int **in_shape_ndim, const int ***in_shape_data),
1106                  (uint32_t *out_shape_size, const int **out_shape_ndim, const int ***out_shape_data),
1107                  (uint32_t *aux_shape_size, const int **aux_shape_ndim, const int ***aux_shape_data)
1108 {
1109     if(!result && *arg15)
1110     {
1111         AV *container;
1112         AV *tmp;
1113         int i, j;
1114         container = newAV();
1115         for (i = 0; i < *$1 ; i++)
1116         {
1117             tmp = newAV();
1118             int len = (*$2)[i];
1119             for (j = 0; j < len ; j++)
1120             {
1121                 av_push(tmp, newSViv((*$3)[i][j]));
1122             }
1123             av_push(container, newRV((SV*)tmp));
1124         }
1125         $result = newRV_noinc((SV*)container);
1126         sv_2mortal($result);
1127         argvi++;
1128     }
1129 }
1130 
1131 %typemap(argout) (size_t *in_shape_size, const int **in_shape_ndim, const int64_t ***in_shape_data),
1132                  (size_t *out_shape_size, const int **out_shape_ndim, const int64_t ***out_shape_data),
1133                  (size_t *aux_shape_size, const int **aux_shape_ndim, const int64_t ***aux_shape_data)
1134 {
1135     if(!result && *arg15)
1136     {
1137         AV *container;
1138         AV *tmp;
1139         size_t i;
1140         int j;
1141         container = newAV();
1142         for (i = 0; i < *$1 ; i++)
1143         {
1144             tmp = newAV();
1145             int len = (*$2)[i];
1146             for (j = 0; j < len ; j++)
1147             {
1148                 av_push(tmp, newSVnv((double)((*$3)[i][j])));
1149             }
1150             av_push(container, newRV((SV*)tmp));
1151         }
1152         $result = newRV_noinc((SV*)container);
1153         sv_2mortal($result);
1154         argvi++;
1155     }
1156 }
1157 
1158 %typemap(in,numinputs=0) (uint32_t *in_type_size, const int **in_type_data)
1159                          (uint32_t temp1, int *temp2),
1160                          (uint32_t *out_type_size, const int **out_type_data)
1161                          (uint32_t temp1, int *temp2),
1162                          (uint32_t *aux_type_size, const int **aux_type_data)
1163                          (uint32_t temp1, int *temp2)
1164 {
1165     $1 = &temp1;
1166     $2 = &temp2;
1167     *$1 = 0;
1168 }
1169 
1170 %typemap(argout)  (uint32_t *in_type_size,  const int **in_type_data),
1171                   (uint32_t *out_type_size, const int **out_type_data),
1172                   (uint32_t *aux_type_size, const int **aux_type_data)
1173 
1174 {
1175     if(!result && *arg11)
1176     {
1177         AV *container;
1178         int i;
1179         container = newAV();
1180         for (i = 0; i < *$1 ; i++)
1181         {
1182             av_push(container, newSViv((*$2)[i]));
1183         }
1184         $result = newRV_noinc((SV*)container);
1185         sv_2mortal($result);
1186         argvi++;
1187     }
1188 }
1189 
1190 %typemap(in,numinputs=0) (uint32_t* num_in_args,
1191                           NDArrayHandle** in_args,
1192                           NDArrayHandle** arg_grads)
1193                          (uint32_t temp1,
1194                          NDArrayHandle* temp2,
1195                          NDArrayHandle* temp3)
1196 {
1197     $1 = &temp1;
1198     $2 = &temp2;
1199     $3 = &temp3;
1200     *$1 = 0;
1201 }
1202 
1203 %typemap(argout) (uint32_t* num_in_args,
1204                   NDArrayHandle** in_args,
1205                   NDArrayHandle** arg_grads)
1206 {
1207     if(!result)
1208     {
1209         AV *container1 = newAV();
1210         AV *container2 = newAV();
1211         for (int i = 0; i < *$1 ; i++)
1212         {
1213             av_push(container1, SvREFCNT_inc(SWIG_NewPointerObj(SWIG_as_voidptr((*$2)[i]), SWIGTYPE_p_MXNDArray, 0)));
1214             av_push(container2, (*$3)[i] ? SvREFCNT_inc(SWIG_NewPointerObj(SWIG_as_voidptr((*$3)[i]), SWIGTYPE_p_MXNDArray, 0)) : newSV(0));
1215         }
1216         $result = newRV_noinc((SV*)container1);
1217         sv_2mortal($result);
1218         argvi++;
1219         $result = newRV_noinc((SV*)container2);
1220         sv_2mortal($result);
1221         argvi++;
1222     }
1223 }
1224 
1225 %typemap(in,numinputs=0) (uint32_t* num_aux_states,
1226                           NDArrayHandle** aux_states)
1227                          (uint32_t temp1,
1228                          NDArrayHandle* temp2)
1229 {
1230     $1 = &temp1;
1231     $2 = &temp2;
1232     *$1 = 0;
1233 }
1234 
1235 %typemap(argout) (uint32_t* num_aux_states,
1236                   NDArrayHandle** aux_states)
1237 {
1238     if(!result)
1239     {
1240         AV *container  = newAV();
1241         for (int i = 0; i < *$1 ; i++)
1242         {
1243             av_push(container, SvREFCNT_inc(SWIG_NewPointerObj(SWIG_as_voidptr((*$2)[i]), SWIGTYPE_p_MXNDArray, 0)));
1244         }
1245         $result = newRV_noinc((SV*)container);
1246         sv_2mortal($result);
1247         argvi++;
1248     }
1249 }
1250 
1251 %typemap(in) (int* shared_buffer_len,
1252               const char** shared_buffer_name_list,
1253               NDArrayHandle* shared_buffer_handle_list,
1254               const char*** updated_shared_buffer_name_list,
1255               NDArrayHandle** updated_shared_buffer_handle_list)
1256               (int temp1,
1257                char* temp2,
1258                NDArrayHandle temp3,
1259                char** temp4,
1260                NDArrayHandle* temp5)
1261 {
1262     HV *temphv;
1263     char *key;
1264     SV *val;
1265     I32 len;
1266     int res;
1267     int i = 0;
1268     int hash_len;
1269     $1 = &temp1;
1270     $2 = &temp2;
1271     $3 = &temp3;
1272     $4 = &temp4;
1273     $5 = &temp5;
1274     if (!SvROK($input))
1275     {
1276         *$1 = -1;
1277         $2 = NULL;
1278         $3 = NULL;
1279     }
1280     else
1281     {
1282         if (SvTYPE(SvRV($input)) != SVt_PVHV)
1283             croak("Argument $argnum is not a hash.");
1284         temphv = (HV*)SvRV($input);
1285         *$1 = hv_iterinit(temphv);
1286         if(*$1)
1287         {
1288             $2 = (char**)safemalloc((*$1)*sizeof(char*));
1289             $3 = (void**)safemalloc((*$1)*sizeof(void*));
1290             while ((val = hv_iternextsv(temphv, &key, &len)))
1291             {
1292                 $2[i] = key;
1293                 res = SWIG_ConvertPtr(val,SWIG_as_voidptrptr(&($3[i])), 0, 0);
1294                 if (!SWIG_IsOK(res)) {
1295                     SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "NDArray""'");
1296                 }
1297                 i++;
1298             }
1299         }
1300         else
1301         {
1302             $2 = NULL;
1303             $3 = NULL;
1304         }
1305     }
1306 }
1307 
1308 %typemap(freearg) (int* shared_buffer_len,
1309                    const char** shared_buffer_name_list,
1310                    NDArrayHandle* shared_buffer_handle_list,
1311                    const char*** updated_shared_buffer_name_list,
1312                    NDArrayHandle** updated_shared_buffer_handle_list)
1313 {
1314     Safefree($2);
1315     Safefree($3);
1316 }
1317 
1318 %typemap(argout)  (int* shared_buffer_len,
1319                    const char** shared_buffer_name_list,
1320                    NDArrayHandle* shared_buffer_handle_list,
1321                    const char*** updated_shared_buffer_name_list,
1322                    NDArrayHandle** updated_shared_buffer_handle_list)
1323 
1324 {
1325     if(!result)
1326     {
1327         HV* hash = newHV();
1328         for(int j = 0; j < *$1; j++)
1329         {
1330             hv_store(hash, (*$4)[j], strlen((*$4)[j]), SvREFCNT_inc(SWIG_NewPointerObj(SWIG_as_voidptr((*$5)[j]), SWIGTYPE_p_MXNDArray, 0)), 0);
1331         }
1332         $result = newRV_noinc((SV*)hash);
1333         sv_2mortal($result);
1334         argvi++;
1335     }
1336 }
1337 
1338 
1339 %typemap(in) (uint32_t x)
1340 {
1341     union fbits u;
1342     u.f = SvNV($input);
1343     $1 = u.x;
1344 }
1345 
1346 %typemap(out) (uint16_t)
1347 {
1348     $result = newSViv($1);
1349     sv_2mortal($result);
1350     argvi++;
1351 }
1352 
1353 %typemap(in) (uint16_t x)
1354 {
1355     $1 = SvIV($input);
1356 }
1357 
1358 %typemap(out) (uint32_t)
1359 {
1360     union fbits u;
1361     u.x = $1;
1362     $result = newSVnv(u.f);
1363     sv_2mortal($result);
1364     argvi++;
1365 }
1366 
1367 %typemap(in,numinputs=0) (MXKVStoreUpdater* updater)
1368 {
1369     $1 = KVStore_callback;
1370 }
1371 
1372 %typemap(in,numinputs=0) (MXKVStoreStrUpdater* updater)
1373 {
1374     $1 = KVStoreStr_callback;
1375 }
1376 
1377 %typemap(in,numinputs=0) (MXKVStoreServerController* controller)
1378 {
1379     $1 = KVStoreServer_callback;
1380 }
1381 
1382 %typemap(in,numinputs=0) (ExecutorMonitorCallback callback)
1383 {
1384     $1 = ExecutorMonitor_callback;
1385 }
1386 
1387 %typemap(in) (void* callback_handle)
1388 {
1389     $1 = (void*)newSVsv($input);
1390 }
1391