# SWIG typemap for ta-lib

**URL:** <https://www.ruby-forum.com/t/swig-typemap-for-ta-lib/88662>\
**Category:** Ruby\
**Created:** [March 13, 2007, 12:05pm UTC](https://www.ruby-forum.com/t/swig-typemap-for-ta-lib/88662 "2007-03-13T12:05:52Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [March 13, 2007, 12:05pm UTC](https://www.ruby-forum.com/t/swig-typemap-for-ta-lib/88662/1 "2007-03-13T12:05:52Z")

</div>

I was trying to swig a function in ta-lib (TA-Lib provides common  
functions for the technical analysis of financial market data)  
[http://ta-lib.org/index.html](http://ta-lib.org/index.html)

the c functuon api

TA\_RetCode TA\_MA( int startIdx,  
int endIdx,  
const double inReal[],  
int optInTimePeriod,  
int optInMAType,  
int \*outBegIdx,  
int \*outNbElement,  
double outReal[],  
)

===========

# the c call

TA\_Real closePrice[400];  
TA\_Real out[400];  
TA\_Integer outBeg;  
TA\_Integer outNbElement;

/\* … initialize your closing price here… \*/

retCode = TA\_MA( 0, 399,  
&closePrice[0],  
30,TA\_MAType\_SMA,  
&outBeg, &outNbElement, &out[0] );

/\* The output is displayed here \*/  
for( i=0; i \< outNbElement; i++ )  
printf( “Day %d = %f\n”, outBeg+i, out[i] );

================

the query’‘’‘’’

what should be the typemap

for argument

```
             1>const double inReal[],
              2>int *outBegIdx,
              3>int *outNbElement,
              4>double outReal[],

```

=============

regards

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [March 14, 2007, 11:51am UTC](https://www.ruby-forum.com/t/swig-typemap-for-ta-lib/88662/2 "2007-03-14T11:51:17Z")

</div>

Thanks for your lead.  
It is lot clear now … how to go about it.  
Still I am fuzzy on a couple of things.  
Could you pl guide…

> in ruby use it as  
> closePrice = Array.new()  
> data\_inp = closePrice[0…399]  
> data\_arr = ModuleExp::TA\_MA( data\_inp, 30, ModuleExp::TA\_MAType\_SMA)

So are you suggesting that i need not pass startIdx,endIdx in the  
input. But these values I understand is required … this is to  
sometimes specify a range on which to run the function .  
What I am confused about is …ModuleExp::TA\_MAType\_SMA… is this a  
constant that you are suggesting to pass along?

> ```
> /* Get the length of the array */
> {
> /* Convert Ruby Object Fixnum to unsigned char */
> $1[i]= (double)?????(*ptr); // here i don't remember the macro
> 
> ```
> 
> to convert something like FIX2INT for float  
> }

here I used $1[i]= NUM2DBL(\*ptr);  
is that OK?

> double arr\_res[400];  
> Here I need to dimensionise the arr\_res to the size of the input  
> array instead of 400. So i need to get the size variable in the  
> previous typemap declaration. But how can i use the size variable  
> here… it was a local variable only.

> ```
> const double inReal[],
> const double inReal[],
> int optInTimePeriod,
> int optInMAType,
> int *outBegIdx,
> int *outNbElement,
> double outReal[])
> 
> ```

I did not get this one clearly… TA\_Retcode is the output type.  
Can’t i get it in ruby?Only thing that i am getting back here is the  
outReal[] array i think.

> {
> 
> ```
> int iStartIx = *arg6;
> int iLen = iStartIx + *arg7;
> 
> VALUE arr = rb_ary_new2(iLen);
> 
> for ( int i = iStartIx; i < iLen; i++ )
> rb_ary_push(arr, INT2FIX((*arg8)[i]));
> $result = arr;
> 
> ```

the \*arg8 contains floating point number so will INT2FIX work?

> }
> 
> it is not tested but this give you the idea how to make the i file.
> 
> Regards

Thanks again …

Regards

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [March 13, 2007, 6:31pm UTC](https://www.ruby-forum.com/t/swig-typemap-for-ta-lib/88662/3 "2007-03-13T18:31:07Z")

</div>

On 13 Mrz., 12:03, “BENI” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> int *outBegIdx,
> 
> ```
> 
> TA\_Real out[400];  
> /\* The output is displayed here \*/
> 
> ```
> 1>const double inReal[],
> 2>int *outBegIdx,
> 3>int *outNbElement,
> 4>double outReal[],
> 
> ```
> 
> =============
> 
> regards

in ruby use it as  
closePrice = Array.new()  
data\_inp = closePrice[0…399]  
data\_arr = ModuleExp::TA\_MA( data\_inp, 30, ModuleExp::TA\_MAType\_SMA)

In .i file you should define  
%typemap(in)(int startIdx,  
int endIdx,  
const double inReal[]  
)  
{

```
   Check_Type($input, T_ARRAY);

/* Get the length of the array */
int size = RARRAY($input)->len;
int i;
$3 = (unsigned char*) malloc(size * sizeof(double));
$2 = size;
$1 = 0;

// copy the ruby array in the new allocated buffer
/* Get the first element in memory */
VALUE *ptr = RARRAY($input)->ptr;
for (i=0; i < size; i++, ptr++)
{
    /* Convert Ruby Object Fixnum to unsigned char */
    $1[i]= (double)?????(*ptr); // here i don't remember the macro

```

to convert something like FIX2INT for float  
}  
}

%typemap(in)(int optInMAType,  
int \*outBegIdx,  
int \*outNbElement,  
double outReal[]  
)  
{  
int out\_beg\_ix = 0;  
int out\_n\_ele = 0;  
double arr\_res[400];

$1 = NUM2INT(optInMAType);  
$2 = &out\_beg\_ix;  
$3 = &out\_n\_ele;  
&4 = arr\_res;

}

%typemap(freearg) (int startIdx,  
int endIdx,  
const double inReal[],  
int optInTimePeriod,  
int optInMAType,  
int \*outBegIdx,  
int \*outNbElement,  
double outReal[]) {  
free((double \*) $1);  
}

%typemap(out)TA\_RetCode TA\_MA( int startIdx,  
int endIdx,  
const double inReal[],  
int optInTimePeriod,  
int optInMAType,  
int \*outBegIdx,  
int \*outNbElement,  
double outReal[]  
{

```
   int iStartIx = *arg6;
   int iLen = iStartIx + *arg7;

    VALUE arr = rb_ary_new2(iLen);

    for ( int i = iStartIx; i < iLen; i++ )
        rb_ary_push(arr, INT2FIX((*arg8)[i]));
    $result = arr;

```

}

it is not tested but this give you the idea how to make the i file.

Regards

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [March 14, 2007, 10:51pm UTC](https://www.ruby-forum.com/t/swig-typemap-for-ta-lib/88662/4 "2007-03-14T22:51:28Z")

</div>

On Mar 14, 11:45 am, “BENI” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > data\_arr = ModuleExp::TA\_MA( data\_inp, 30, ModuleExp::TA\_MAType\_SMA)
> 
> > ```
> > int size = RARRAY($input)->len;
> > /* Convert Ruby Object Fixnum to unsigned char */
> > int *outBegIdx,
> > 
> > ```
> 
> previous typemap declaration. But how can i use the size variable
> 
> > ```
> > free((double *) $1);
> > 
> > ```
> 
> > Regards
> 
> Thanks again …
> 
> Regards

Sorry for some errors.  
Your questions.  
If you use TA\_MAType\_SMA in the C function and you want to use it  
also in ruby, you have to export it.  
In Ruby I like to use all input parameters as function parameters.  
Out parameters on the left side as result. If you are also interested  
an TA\_Retcode you have to change the typemap(out). Afterwards you can  
use in ruby this:  
ta\_res, data\_arr\_out = ModuleExp::TA\_MA( data\_inp, 30,  
ModuleExp::TA\_MAType\_SMA)

in .i file:  
%typemap(out)TA\_RetCode TA\_MA( int startIdx,  
int endIdx,  
const double inReal[],  
int optInTimePeriod,  
int optInMAType,  
int \*outBegIdx,  
int \*outNbElement,  
double outReal[]  
{

```
   int iStartIx = *arg6;
   int iLen = iStartIx + *arg7;
   VALUE arr_results = rb_ary_new2(2) // 2 elements as result
   rb_ary_push(arr_results, INT2FIX(result)); // first is

```

TA\_Retcode

```
   VALUE arr_data = rb_ary_new2(iLen); // data array

    for ( int i = iStartIx; i < iLen; i++ )
        rb_ary_push(arr_data, rb_float_new((*arg8)[i]));

    rb_ary_push(arr_results, arr_data); // second array of data

    $result = arr_results

```

}

here you are right, INT2FIX doesn’t work but rb\_float\_new should be.  
NUM2DBL for inputs should be also ok.

If you need to pass startIdx,endIdx as input, you have to modify the  
typemap(in)

%typemap(in)(const double inReal[])  
{

```
   Check_Type($input, T_ARRAY);

/* Get the length of the array */
int size = RARRAY($input)->len;
int i;
$1 = (unsigned char*) malloc(size * sizeof(double));

// copy the ruby array in the new allocated buffer
/* Get the first element in memory */
VALUE *ptr = RARRAY($input)->ptr;
for (i=0; i < size; i++, ptr++)
{
    /* Convert Ruby Object Fixnum to unsigned char */
    $1[i]= (double)NUM2DBL(*ptr);
}

```

}

If you don’t like a maxsize for output array, like double  
arr\_res[MAX\_OUT\_DATA];  
you can use:  
arg8 = (unsigned char\*) malloc(size \* sizeof(double));  
inside %typemap(in)(const double inReal[])  
I don’t know if it is exact, but you can look inside the generated  
code if all is set like you want (I use swig with c++ and I expect a  
function called \_wrap\_TA\_MA inside generated code).  
Don’t forget to free arg8 in the typemap.

Cheers  
Igor

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [March 17, 2007, 9:40pm UTC](https://www.ruby-forum.com/t/swig-typemap-for-ta-lib/88662/5 "2007-03-17T21:40:58Z")

</div>

On Mar 15, 1:52 pm, “BENI” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> How do I make SWIG aware of my TA\_Retcode type?  
> int arg2 ;
> 
> ```
> arg3 = (unsigned char*) malloc(size * sizeof(double));
> }
> int out_n_ele = 0;
> 
> ```
> 
> {  
> return vresult;  
> fail:  
> return Qnil;
> 
> }
> 
> Thanks
> 
> Regards

for TA\_RetCode you have to declare in .i file the header file where  
TA\_RetCode is defined. After %module declaration in .i you can use  
%{

#include “xxxxxTA\_RetCodeincludefile.h”  
This to avoid compiler error in your wrap function.

To export TA\_RetCode to ruby you can use, at the end of .i file, this  
declaration:  
%include “xxxxxTA\_RetCodeincludefile.h”

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [March 15, 2007, 1:56pm UTC](https://www.ruby-forum.com/t/swig-typemap-for-ta-lib/88662/6 "2007-03-15T13:56:12Z")

</div>

I got most of your points.

I am still confused with TA\_RetCode

I am being bugged by the compiler

C:\talib\ta-lib\swig\ide\msvc\talibruby\rubytalibdll  
\rubytalib\_wrap.c(1623) : error C2065: ‘TA\_RetCode’ : undeclared  
identifier

How do I make SWIG aware of my TA\_Retcode type?

am I making some mistake pertaining to header inclusion in .i file ?

a snap of my wrap fn

# ===========================================

SWIGINTERN VALUE  
\_wrap\_TA\_MA(int argc, VALUE \*argv, VALUE self) {  
int arg1 ;  
int arg2 ;  
double \*arg3 ;  
int arg4 ;  
int arg5 ;  
int \*arg6 = (int \*) 0 ;  
int \*arg7 = (int \*) 0 ;  
double _arg8 ;  
TA\_RetCode result; /_ I did not get it here \*/  
int val4 ;  
int ecode4 = 0 ;  
VALUE vresult = Qnil;

if ((argc \< 3) || (argc \> 3)) {  
rb\_raise(rb\_eArgError, “wrong # of arguments(%d for 3)”,argc);  
SWIG\_fail;  
}  
{  
Check\_Type(argv[0], T\_ARRAY);

```
/* Get the length of the array */
int size = RARRAY(argv[0])->len;
int i;
arg3 = (unsigned char*) malloc(size * sizeof(double));
arg2 = size;
arg1 = 0;

// copy the ruby array in the new allocated buffer
/* Get the first element in memory */
VALUE *ptr = RARRAY(argv[0])->ptr;
for (i=0; i < size; i++, ptr++)
{
  /* Convert Ruby Object Fixnum to unsigned char */
  arg1[i]= NUM2DBL(*ptr);
}

```

}  
ecode4 = SWIG\_AsVal\_int(argv[1], &val4);  
if (!SWIG\_IsOK(ecode4)) {  
SWIG\_exception\_fail(SWIG\_ArgError(ecode4), “in method '” “TA\_MA”  
“’, argument " “4"” of type '” “int”"’");  
}  
arg4 = (int)(val4);  
{  
int out\_beg\_ix = 0;  
int out\_n\_ele = 0;  
double arr\_res[400];

```
arg5 = NUM2INT(optInMAType);
arg6 = &out_beg_ix;
arg7 = &out_n_ele;
arg8 = arr_res;

```

}  
result = TA\_MA(arg1,arg2,(double const  
(\*))arg3,arg4,arg5,arg6,arg7,arg8);  
{  
int iStartIx = \*arg6;  
int iLen = iStartIx + \*arg7;

```
VALUE arr = rb_ary_new2(iLen);

for ( int i = iStartIx; i < iLen; i++ )
rb_ary_push(arr, INT2FIX((*arg8)[i]));
vresult = arr;

```

}  
return vresult;  
fail:  
return Qnil;  
}

Thanks

Regards

---

<div class="post-metadata">

**Author:** ![BENI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BENI](https://www.ruby-forum.com/u/BENI)\
**Post date:** [March 20, 2007, 12:30pm UTC](https://www.ruby-forum.com/t/swig-typemap-for-ta-lib/88662/7 "2007-03-20T12:30:45Z")

</div>

Thanks a lot for your help.

I have been able to port all the functions .

For the group info… i have built the dll .

i am writing the test cases now…

Testing will be a long affair i feel…

btw :::: if any one is interested in using it pl send me mail… i  
will attach the dll

#########################################################################  
just a sample of a couple of functions  
#########################################################################

C:\talib\ta-lib\swig\ide\msvc\talibruby\rubytalibdll\Debug\>ruby  
rubytalibtest.rb

TOTAL DATA POINTS FOR TEST: 252  
################################################################################

Start of Rubytalib test… Rubytalib version:0.3.0 (Mar 20 2007  
07:33:13)  
################################################################################

TA\_MAX OUTPUT Maximum price ======\>137.88  
TA\_MAXINDEX OUTPUT Max Index =======\>131  
TA\_SUM of the lot ==========\>27133.035  
TA\_MIDPOINTof the lot ==========\>109.6275  
TA\_MA of the lot(Simple over 200 days) ==========\>[108.900525,  
108.882808333333,  
108.864073922056, 108.686321942732, 108.539592371163,  
108.393626277918, 108.265  
331489083, 108.11343764342, 107.982358661893, 107.885519272223,  
107.774718085435  
, 107.64571591543, 107.513619239655, 107.354876759658,  
107.184678980955, 107.052  
891130398, 106.919230522136, 106.82053171097, 106.702914480015,  
106.595124286184  
, 106.470396681347, 106.352482286507, 106.227084452811,  
106.145222915967, 106.12  
328039939, 106.140660693924, 106.139858099954, 106.123541103935,  
106.11236159046  
3, 106.093233614438, 106.063052185439, 106.036753158718,  
106.029123774054, 106.0  
87241945457, 106.18587635396, 106.289698479791, 106.409004962579,  
106.4782685947  
92, 106.50336044957, 106.535167808281, 106.56218106392,  
106.566537471244, 106.59  
2641576008, 106.626545639928, 106.652152150974, 106.68665809972,  
106.69972617833  
, 106.718833380536, 106.748994242421, 106.779452011153,  
106.801547016017, 106.82  
0934607898, 106.831373069511]  
TA\_MA of the lot(Exponential over 200 days)  
==========\>[117.055064179104, 117.03  
7347512438, 117.017659701493, 116.838161691542, 116.688085323383,  
116.5373699004  
97, 116.402868905473, 116.243448756219, 116.103308706468,  
115.995995024876, 115.  
87336119403, 115.731210945274, 115.58474800995, 115.410468159204,  
115.2234987562  
19, 115.073227114428, 114.919625124378, 114.799614925373,  
114.659313930348, 114.  
527388308458, 114.377241542289, 114.232458706468, 114.078708457711,  
113.96694203  
9801, 113.91362238806, 113.898365422886, 113.863886069652,  
113.812656218905, 113  
.765403482587, 113.709307462687, 113.641081343284, 113.575600995025,  
113.5276246  
26866, 113.544417164179, 113.601007960199, 113.662423134328,  
113.738955223881, 1  
13.765069154229, 113.746379353234, 113.733454477612, 113.714782835821,  
113.67246  
0696517, 113.650754228856, 113.635928855721, 113.612107960199,  
113.596458208955,  
113.558767412935, 113.526387562189, 113.504396766169,  
113.481970646766, 113.450  
549004975, 113.415719402985, 113.371152487562]

#################################################################################

Regards.

Rajib
